Hie with the Pie POJ - 3311

原题链接

考察:状压dp

本题是731. 毕业旅行问题的延伸

思路:

       与上面那道题不同的是每个点至少走一次,而不是只能走一次.普通的dp求出的是0到i点的最短距离(且每个点都经过一次),但这里我们还需要回程,也就是还需要求出i到0点的最短距离.我们手操可以发现ans=每个点都经过一次的最短距离+回程的最短距离.第一部分可以通过dp求出,第二部分可以用floyd.

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 using namespace std;
 6 const int N = 11,INF = 0x3f3f3f3f;
 7 int w[N][N],n,f[1<<N][N];
 8 int main()
 9 {
10     while(scanf("%d",&n)!=EOF&&n)
11     {
12         n++;
13         int ans  = INF,all = (1<<n)-1; memset(f,0x3f,sizeof f);
14         for(int i=0;i<n;i++)
15           for(int j=0;j<n;j++) scanf("%d",&w[i][j]);
16         for(int i=0;i<n;i++)
17           for(int j=0;j<n;j++)
18             for(int k=0;k<n;k++)
19               w[i][j] = min(w[i][k]+w[k][j],w[i][j]);
20         f[1][0] = 0;
21         for(int i=0;i<1<<n;i++)
22           for(int j=0;j<n;j++)
23            if(i>>j&1)
24            {
25                 for(int k=0;k<n;k++)
26                if(i-(1<<j)>>k&1)
27                  f[i][j] = min(f[i-(1<<j)][k]+w[k][j],f[i][j]);
28              if(i==all)
29                ans = min(ans,f[i][j]+w[j][0]);
30            }     
31         printf("%d\n",ans);
32     }
33     return 0;
34 }

 

posted @ 2021-02-14 13:07  acmloser  阅读(44)  评论(0编辑  收藏  举报