cf339-c

题意:往天平两边按照左右左右的顺序放置砝码,往左放了砝码后,左边需要比右边重,往右边放置砝码后,右边需要比左边重,给出现有的砝码种类数量不限,求一个放置的解。
方法:dp,令dp[i][j][k]表示,第k个放置重量为i,比对面重了j,那么他就可以被
dp[t][i-j][k-1]转移到,即当前放i重了j,那么上一个一定比上上一个重了i-j,枚举t即可。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<climits>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<set>
    #include<map>
    //#include<regex>
    #include<cstdio>
    #define up(i,a,b)  for(int i=a;i<b;i++)
    #define dw(i,a,b)  for(int i=a;i>b;i--)
    #define upd(i,a,b) for(int i=a;i<=b;i++)
    #define dwd(i,a,b) for(int i=a;i>=b;i--)
    //#define local
    typedef long long ll;
    const double esp = 1e-6;
    const double pi = acos(-1.0);
    const int INF = 0x3f3f3f3f;
    const int inf = 1e9;
    using namespace std;
    int read()
    {
    	char ch = getchar(); int x = 0, f = 1;
    	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    	return x * f;
    }
    typedef pair<int, int> pir;
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lrt root<<1
    #define rrt root<<1|1
    int dp[20][20][1005];//fang k duo j di i
    char s[200];
    int cnt[200];
    int m;
    vector<int >vec;
    void findpath(int nowwei,int dis,int dep)
    {
    	if (dep == 0)return;
    	vec.push_back(nowwei);
    	upd(i, 1, 10)
    	{
    		if (dp[i][nowwei - dis][dep - 1]&&i!=nowwei) {
    			findpath(i, nowwei - dis, dep - 1); return;
    		}
    	}
    }
    int main()
    {
    	cin >> s;
    	m = read();
    	up(i, 0, 10)if (s[i] == '1')cnt[i + 1] = 1;
    	upd(i, 1, 10)if(cnt[i])dp[i][i][1] = 1;
    	upd(i, 2, m)
    	{
    		upd(j, 1, 10)
    		{
    			upd(k, 1, 10)
    			{
    				if (!cnt[k])continue;
    				if (k <= j)continue;
    				upd(p, 1, 10)
    				{
    					if(cnt[p]&&p!=k)
    						dp[k][j][i] |= dp[p][k - j][i-1];
    				}
    			}
    		}
    	}
    	upd(j, 1, 10)upd(k, 1, 10)if (dp[j][k][m]) {
    		findpath(j, k, m); goto ed;
    	}
    ed:	if (vec.size() == 0) { cout << "NO" << endl; return 0; }
    	cout << "YES" << endl;
    	reverse(vec.begin(), vec.end());
    	for (auto k : vec)cout << k << " ";
    	return 0;
    }

说实话没太明白网上暴力dfs的复杂度,就算剪了支感觉也很慢啊。

posted @ 2019-09-26 15:05  LORDXX  阅读(190)  评论(0编辑  收藏  举报