写给(跟我一样 没学过 状压 对题解状压有疑问的友友
  • 板块P1433 吃奶酪
  • 楼主EAZINZERO
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/7/20 10:41
  • 上次更新2023/11/3 08:42:53
查看原帖
写给(跟我一样 没学过 状压 对题解状压有疑问的友友
892284
EAZINZERO楼主2023/7/20 10:41

以下观点 是个人理解 如有错误之处 欢迎指正!

对于本题的状态压缩 是指压缩路径;

以下疑问 是本人对novax 大佬的题解 的疑问

比如 11 的二进制是 1011(表示 走过点 1,2,4

左边第一位是1号点

一个奶酪 代表一个点

dp[i][k]

的含义 是 当前 在 i 点 经过路径 k 时 的最短距离

dp数组初始化:
   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 & (1 << (i - 1)) 的 理解

举个例子 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 - (1 << (i - 1)] 的理解

举个例子 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

2023/7/20 10:41
加载中...