NC15832 Most Powerful

题目链接

题目

题目描述

Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two atoms perform when collided and the power every two atoms can produce.

You are to write a program to make it most powerful, which means that the sum of power produced during all the collides is maximal.

输入描述

There are multiplecases. The first line of each case has an integer N (2 <= N <= 10), whichmeans there are N atoms: A1, A2, ... , AN.Then N lines follow. There are N integers in each line. The j-th integer on thei-th line is the power produced when Ai and Aj collidewith Aj gone. All integers are positive and not larger than 10000.The last case isfollowed by a 0 in one line.There will be no morethan 500 cases including no more than 50 large cases that N is 10.

输出描述

Output the maximalpower these N atoms can produce in a line for each case.

示例1

输入

2
0 4
1 0
3
0 20 1
12 0 1
1 10 0
0

输出

4
22

题解

知识点:状压dp。

经典的TSP问题。这道题由于可以随便找一个 \(A\) 撞随便一个 \(B\) ,所以没必要记录上一个原子是啥,设 \(dp[st]\) 表示状态 \(st\) 的最大值。由于 \(A\)\(B\) 只会消失 \(B\) 并得到 \((A,B)\) 的能量,因此 \(A\) (编号 \(i\) )要满足状态中没用过,\(B\) (编号 \(j\) )满足状态中用过,于是有转移方程:

\[dp[st] = max(dp[st], dp[st \wedge (1 << (j - 1))] + g[i][j]) \]

用记忆化搜索也能写。

时间复杂度 \(O(n^22^n)\)

空间复杂度 \(O(2^n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int n;
int g[17][17];
int dp[1 << 11];

int dfs(int st) {
    if (~dp[st]) return dp[st];
    for (int i = 1;i <= n;i++) {
        if ((st >> (i - 1)) & 1) continue;
        for (int j = 1;j <= n;j++) {
            if (!((st >> (j - 1)) & 1)) continue;
            dp[st] = max(dp[st], dfs(st ^ (1 << (j - 1))) + g[i][j]);
        }
    }
    return dp[st];
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    while (cin >> n, n) {
        for (int i = 1;i <= n;i++)
            for (int j = 1;j <= n;j++)
                cin >> g[i][j];
        memset(dp, -1, sizeof(dp));
        int ans = 0;
        dp[0] = 0;
        for (int i = 1;i <= n;i++) {
            ans = max(ans, dfs(((1 << n) - 1) ^ (1 << (i - 1))));
        }
        cout << ans << '\n';
    }
    return 0;
}
posted @ 2022-09-03 11:52  空白菌  阅读(22)  评论(0编辑  收藏  举报