昨晚没注意k的范围,当成1e5的数据量去想,不过ABC的题能考察状态压缩还是挺令人震惊的
题意
给定$n$个点,$m$条无向边,边的长度都看作1。之后给$k$个点,问把这$k$个点都走一遍所需要的最短路程。
题解
其实把题意理解后就几乎是状态压缩的模板题,只不过$k$个点两两间的距离没有给出,由于每条边的长度都可以看作1,所以对这$k$个点每个点跑一次$bfs$就可以得出每个点到其余点的最短距离。
用$dp[mask][i]$进行状态压缩dp,$mask$是$k$位的二进制数,第$i$位的0或1表示是否经过这个点。所以这个$dp$数组就表示经过$mask$表示的这些点并且最后走的点是$i$的最短路。如果$mask$的第j位是0,用$next$表示$mask$第$j$位是1的二进制表示,那么经过$mask$表示的点并从$i$出来到达$j$的最短路程为$dp[mask][i]+dis[i][j]$,可以得到状态转移方程:
\[dp[next][j] = min(dp[next][j], dp[mask][i]+dis[i][j])\]得到所有的状态后,最终答案可以用如下方程更新:
\[ans = \min_{1<=i<=k}(dp[(1<<k)-1][i])\]$(1«k)-1$表示所有点都经过(即11…111),求一遍以每个点为最后一个点的最小值。
代码
1 | |