链接:点击打开链接
题意:n个城市,m条路,每个城市最多经过两次,遍历所有城市最小的费用是多少
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; int three[15]={1,3,9,27,81,243,729,2187,6561,19683,59049}; int d[20][20],dp[60005][15],vis[60005][15]; int main(){ char str[1005]; int V,m,i,j,k,s,u,v,w,ans,tmp,sign; for(i=0;i<=three[10];i++){ tmp=i; for(j=0;j<10;j++){ vis[i][j]=tmp%3; tmp/=3; } } while(scanf("%d%d",&V,&m)!=EOF&&V){ memset(d,INF,sizeof(d)); memset(dp,INF,sizeof(dp)); for(i=0;i<V;i++) dp[three[i]][i]=0; for(i=0;i<m;i++){ scanf("%d%d%d",&u,&v,&w); d[u-1][v-1]=min(d[u-1][v-1],w); d[v-1][u-1]=d[u-1][v-1]; } //有重边 ans=INF; for(s=0;s<three[V];s++){ //因为每个点最多经过两回,因此 sign=0; //就是TSP变为三进制,剩下跟二进 for(u=0;u<V;u++){ //制时一样 if(vis[s][u]==0) sign=1; if(dp[s][u]!=INF) for(v=0;v<V;v++) if(vis[s][v]!=2&&d[u][v]!=INF) dp[s+three[v]][v]=min(dp[s+three[v]][v],dp[s][u]+d[u][v]); } if(sign==0) //最后不好判断是否有没走过的点 for(i=0;i<V;i++) //因此在中间判断 ans=min(ans,dp[s][i]); } if(ans>=INF) puts("-1"); else printf("%d\n",ans); } return 0; }