zoukankan      html  css  js  c++  java
  • 2019牛客国庆集训派对day3 G排列(状压dp)

    题目传送门

    一道很好的状压DP,状态是当前的占位情况,排序操作和第21次CSP认证的第四题作用类似。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1 << 22;
    const ll inf = 1e15;
    
    int n, m, x, y;
    int num[N], p[22];
    ll dp[N];
    vector<int> vt[22];
    
    int main(){
        for(int i = 1; i < N; ++i)  num[i] = num[i - (i & -i)] + 1;
        while(scanf("%d%d", &n, &m) != EOF){
            for(int i = 0; i < n; ++i)  scanf("%d", &p[i]), vt[i].clear();
            for(int i = 0; i < (1 << n); ++i)  dp[i] = inf;
            while(m--){
                scanf("%d%d", &x, &y);
                vt[x - 1].emplace_back(y - 1);
                vt[y - 1].emplace_back(x - 1);
            } 
            dp[0] = 0;
            // 按照从小到大的顺序插值,满足绝对值的条件
            sort(p, p + n);
            // dp[i]代表i表示的位置填充状态的最小值
            for(int i = 0; i < (1 << n); ++i){
                for(int t = 0; t < n; ++t) if(!(i >> t & 1)){
                    int cnt = 0;
                    for(auto &x : vt[t]){
                        if(i >> x & 1)  ++cnt;	// 若第x个座位已经被包含,该座位上的值一定小于当前要插的值 
                        else  --cnt;
                    }
                    dp[i | (1 << t)] = min(dp[i | (1 << t)], dp[i] + 1LL * p[num[i]] * cnt);
                }
            }
            printf("%lld
    ", dp[(1 << n) - 1]);
        }
        return 0;
    }
    
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    C++多态深入分析!
    字符编码总结
    算法:并查集
    树的非递归遍历:一种很好的算法
    算法:快速排序
    算法:堆排序
    字符串匹配:KMP算法, Boyer-Moore算法理解与总结
    shodan搜索
    google hacking 语法
    FOFA的搜索语句
  • 原文地址:https://www.cnblogs.com/214txdy/p/14151852.html
Copyright © 2011-2022 走看看