洛谷 P1171 售货员的难题(状压dp)

传送门


解题思路

用一个数i的二进制表示某一位的村庄是否已经去过,dp[i][j]表示当前状态i,这一次去的村庄是j的最短路程。

然后就枚举i、j、k(k表示下一个去的村庄),然后在if判断是否符合条件后,用dp[i][j]更新dp[i|1<<(k-1)][k]。

注意边界的处理。

AC代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m[25][25],dp[1048579][25],ans=0x3f3f3f3f;
 4 int main(){
 5     memset(dp,0x3f,sizeof(dp));
 6     cin>>n;
 7     for(int i=1;i<=n;i++){
 8         for(int j=1;j<=n;j++){
 9             cin>>m[i][j];
10         }
11     }
12     dp[1][1]=0;
13     for(int i=1;i<=(1<<n)-1;i++){
14         if(!(i&1)) continue;
15         for(int k=1;k<=n;k++){
16             if(!(i&(1<<(k-1)))) continue;
17             for(int j=2;j<=n;j++){
18                 if(!(i&(1<<(j-1)))) {
19                     dp[i|1<<(j-1)][j]=min(dp[i|1<<(j-1)][j],dp[i][k]+m[k][j]);
20                 }
21             }
22         }
23     }
24     for(int i=1;i<=n;i++) ans=min(ans,dp[(1<<n)-1][i]+m[i][1]);
25     cout<<ans<<endl;
26     return 0;
27 }
原文地址:https://www.cnblogs.com/yinyuqin/p/14028156.html