D - General Weighted Max Matching - DP

D - General Weighted Max Matching - DP_第1张图片D - General Weighted Max Matching - DP_第2张图片D - General Weighted Max Matching - DP_第3张图片分析:

        选择任何一条边都有可能得到最大值,因此可以通过状压DP来做,dp[i]表示第i种状态得到的最大值,i包括了每一位的节点是否被选择,i的二进制表示下,1代表节点被选择,0代表节点没有被选择,那么当i的每一位都是1的时候得到的就是最后的答案。

        分析状态转移,枚举每一种状态,从头开始枚举当前状态i的二进制下的每一位,找到第一位是0的位置表示没有被选择过,作为即将被选择的节点,然后遍历二进制表示的i的每一位,如果存在0,那么可以进行连接,连接后,将选择的这两个位置变成1,得到了一个二进制下的新的状态,那么这个状态就是由当前状态i转移过来的,也就是dp[j] = dp[i] + w,w为权值。

代码:

        

#include 

using namespace std;
using ll = long long;

const int N = 26;

ll g[N][N];
ll dp[1 << N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        for(int j = i + 1; j <= n; j ++) {
            ll x;
            cin >> x;
            g[i][j] = g[j][i] = x;
        }
    }
    for(int i = 0; i < (1 << n) - 1; i ++) {
        int l = 0;
        for(int j = 0; j < n; j ++) {
            if(!(i >> j & 1)) {
                l = j;
                break;
            }
        }
        for(int j = 0; j < n; j ++) {
            if(!(i >> j & 1)) {
                int res = i | (1 << l) | (1 << j);
                dp[res] = max(dp[res], dp[i] + g[l + 1][j + 1]);
            }
        }
    }
    cout << dp[(1 << n) - 1] << '\n';
}

你可能感兴趣的:(动态规划,算法,c++,思维,dp)