解题思路
??状压dp入门题,也是经典的tsp问题。因为tsp问题是np完全问题,所以我们只能考虑通过大量枚举来做。需要注意的一点是,如果走过了1->2->3这样一条路径,要到达第4个点的话,并不一定需要从3出发,只要从前面走过的点出发即可,所以我们并不需要把所以的点按前后顺序走出来的情况全部枚举出来。
??考虑最后一步的情况,我们已经走过了N-1个点,要访问最后一个点,那么结果就是从之前N-1个点之中的一个走过来的最小值。所以问题就是如何表示前面已经走过了哪些点。这里用状压dp的方法,把二进制数的1表示访问过,0表示位访问过,以dp[state][k]表示当前状态最后到达k点的总花费,那么状态转移方程就是dp[i][j] = min(dp[i][j],dp[i-(1<<j)][k]+w[k][j])
int dp[1<<20][20], w[20][20];
int main(void) {
int n; scanf("%d",&n);
for (int i = 0; i<n; ++i)
for (int j = 0; j<n; ++j) scanf("%d",&w[i][j]);
INF(dp); dp[1][0] = 0;
for (int i = 3; i<1<<n; ++i)
for (int j = 0; j<n; ++j)
if (i>>j&1) {
for (int k = 0; k<n; ++k)
if ((i-(1<<j))>>k&1) dp[i][j] = min(dp[i][j],dp[i-(1<<j)][k]+w[k][j]);
//j是枚举结尾的点,而k是枚举上一个状态的点
}
printf("%d\n",dp[(1<<n)-1][n-1]);
return 0;
}