题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5418
题目大意:
T组测试样例,然后n个点,m条边。每一条边的信息是起点,终点,权值(双向图)。
然后问你在每个点都至少访问一次的前提下,最终回到1的最少花费。
具体思路:
dp[i][j]表示在i的二进制中已经访问的点中最终走到 j 的最小花费。
我们在dp的时候,假设要求i -> j ->k, 最好是第一个for循环跑所有的状态,第二个for循环跑i->j,第三个for循环跑j->k。这样能降低复杂度。
注意这里的Map[u][v]是需要求一个最小值的,我们可以先跑一个floyed预处理出来。或者在dp的时候,把每个点的情况都跑一遍(有点spfa的感觉),这样也能更新出最短距离。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 # define ull unsigned long long 6 const int maxn = 2e5+100; 7 const int N = 20; 8 int Map[N][N]; 9 int dp[maxn][N]; 10 int cal(int t) 11 { 12 int ans=0; 13 for(int i=0; i<=16; i++) 14 { 15 if(t&(1<<i)) 16 ans++; 17 } 18 return ans; 19 } 20 void floyed(int n) 21 { 22 for(int i=0; i<n; i++) 23 { 24 for(int j=0; j<n; j++) 25 { 26 for(int k=0; k<n; k++) 27 { 28 Map[j][k]=min(Map[j][k],Map[j][i]+Map[i][k]); 29 } 30 } 31 } 32 } 33 int solve(int n) 34 { 35 int maxstate=(1<<n)-1; 36 for(int i=1; i<=maxstate; i++) 37 { 38 // for(int w=cal(i); w>=0; w--) 39 // { 40 for(int j=0; j<n; j++) 41 { 42 if(dp[i][j]==inf) 43 continue; 44 for(int k=0; k<n; k++) 45 { 46 if(Map[j][k]==inf) 47 continue; 48 dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+Map[j][k]); 49 } 50 } 51 } 52 // } 53 return dp[maxstate][0]; 54 } 55 56 int main() 57 { 58 int T; 59 scanf("%d",&T); 60 while(T--) 61 { 62 memset(Map,inf,sizeof(Map)); 63 memset(dp,inf,sizeof(dp)); 64 int n,m; 65 scanf("%d %d",&n,&m); 66 int st,ed,val; 67 for(int i=1; i<=m; i++) 68 { 69 scanf("%d %d %d",&st,&ed,&val); 70 st--,ed--; 71 Map[st][ed]=Map[ed][st]=min(Map[st][ed],val); 72 } 73 floyed(n); 74 dp[1][0]=0; 75 int ans=solve(n); 76 printf("%d ",ans); 77 } 78 return 0; 79 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define inf 0x3f3f3f3f 5 # define ull unsigned long long 6 const int maxn = 2e5+100; 7 const int N = 20; 8 int Map[N][N]; 9 int dp[maxn][N]; 10 int cal(int t) 11 { 12 int ans=0; 13 for(int i=0; i<=16; i++) 14 { 15 if(t&(1<<i)) 16 ans++; 17 } 18 return ans; 19 } 20 //void floyed(int n) 21 //{ 22 // for(int i=0; i<n; i++) 23 // { 24 // for(int j=0; j<n; j++) 25 // { 26 // for(int k=0; k<n; k++) 27 // { 28 // Map[j][k]=min(Map[j][k],Map[j][i]+Map[i][k]); 29 // } 30 // } 31 // } 32 //} 33 int solve(int n) 34 { 35 int maxstate=(1<<n)-1; 36 for(int i=1; i<=maxstate; i++) 37 { 38 for(int w=cal(i); w>=0; w--) 39 { 40 for(int j=0; j<n; j++) 41 { 42 if(dp[i][j]==inf) 43 continue; 44 for(int k=0; k<n; k++) 45 { 46 if(Map[j][k]==inf) 47 continue; 48 dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+Map[j][k]); 49 } 50 } 51 } 52 } 53 // } 54 return dp[maxstate][0]; 55 } 56 57 int main() 58 { 59 int T; 60 scanf("%d",&T); 61 while(T--) 62 { 63 memset(Map,inf,sizeof(Map)); 64 memset(dp,inf,sizeof(dp)); 65 int n,m; 66 scanf("%d %d",&n,&m); 67 int st,ed,val; 68 for(int i=1; i<=m; i++) 69 { 70 scanf("%d %d %d",&st,&ed,&val); 71 st--,ed--; 72 Map[st][ed]=Map[ed][st]=min(Map[st][ed],val); 73 } 74 //floyed(n); 75 dp[1][0]=0; 76 int ans=solve(n); 77 printf("%d ",ans); 78 } 79 return 0; 80 }