对于本题的状态压缩 是指压缩路径;
比如 11 的二进制是 1011(表示 走过点 1,2,4
左边第一位是1号点
一个奶酪 代表一个点
dp[i][k]
的含义 是 当前 在 i 点 经过路径 k 时 的最短距离
memset(dp,127,sizeof(dp));
ans = dp[0][0];
for(int i = 1;i <= n;i++)
dp[i][1 << (i - 1)] = dis[0][i]; //从 i 出发只经过 i 点
//dp数组初始化
[1 << ( i - 1)] 的理解 举个例子 i = 4;
1 << (4 - 1) 二进制 为 1000
观察一下可以发现 1000 这条路径只走了 第四个点
dp[i][1 << (i - 1)] 的意思就是只走 i 点( 从 i 出发 )的最短距离 (如果 1 << 4 的话 二进制为 100000 会多出一位
if((k & (1 << (i - 1))) == 0) continue; // k 道路没有 走 i 点
举个例子 k = 11,i = 3; // 路径 1011 没有走 第三 个点
(1011) & (0100)= 0 (1011) & (0010) = (0010)二进制 十进制 是2 路径1011 走了第二个点(二进制的运算讲的模棱两可 报意思
dp[i][k] = min(dp[i][k],dis[j][k - (1 << (i - 1)] + dis[i][j]);
开头说了
dp[i][k]
的含义 是 当前 在 i 点 经过路径 k 时 的最短距离 补充一下
dis[j][k - (1 << (i - 1)] + dis[i][j])
的意思 它的意思是 当前在 j 点 不经过 i 点的 距离(之前更新的最短距离 加上 i , j 的距离
举个例子 k = 11 ,i = 4; 11 - 8 = 3; 3 的二进制 0011 对比 10二进制 1011 第四位变为0 就是 不走第四个点(i
dp[i][k] = min(dp[i][k],dis[j][k - (1 << (i - 1)] + dis[i][j]);
整个式子 我理解为试探一下 要不要 从 j 走到 i (要不要经过 j 点;
for(int i = 1;i <= n;i++){
ans = min(ans,dp[i][(1 << n) - 1]);
}
(1 << n) - 1 举个例子 n = 4 1 << 4 就是 10000 (1 << 4 )- 1 = 1111 该路径 表示 四个点都走 上面那个for循环 就是遍历每个出发点 经过所有点 找ans的最小值 ans 初始化为 inf