例题:https://ac.nowcoder.com/acm/contest/996/D
状态dp使用二进制来代替一个位置是否存在,用到了大量的位运算的知识
转移方程:
dp[i | (1 << k)][k] = min(dp[i][j] + ary[j][k], dp[i | (1 << k)][k]);
其中[i | (1 << k)]代表从这个位置去k以后[k]代表现在的位置位于k的位置
dp[i][j]代表之前已经去过i的位置(i用二进制表示后位上为1的代表已经走过,)[j]代表现在位于j的位置,ary[j][k]代表从j到k需要的路程
附上代码:
#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int ary[21][21];
int dp[1 << 21][21];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
cin >> ary[i][j];
}
memset(dp, 0x3f3f3f3f, sizeof dp);
dp[1][0] = 0;
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if (i & (1 << j) && (i & 1)) {
for (int k = 0; k < n; k++) {
if (!(i & (1 << k))) {
dp[i | (1 << k)][k] = min(dp[i][j] + ary[j][k], dp[i | (1 << k)][k]);
}
}
}
}
}
cout << dp[(1 << n) - 1][n-1] << endl;
}</cstring></algorithm></iostream>