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的复杂度,就算剪了支感觉也很慢啊。

猜你喜欢

转载自www.cnblogs.com/LORDXX/p/11591919.html