标签:
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6600 Accepted Submission(s): 2144
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #define M 25 #define INF 0x1f1f1f1f #define N 65000 using namespace std; int n,m; int state[M]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};//state[i]表示第i个点城市状态用3进制表示是多少 int dis[N][M];//dis[i][j]表示i状态j点走过几次 int dp[N][M];//dp[i][j]表示第i个状态最后到达j的最小距离 int g[M][M];//表示两点间的距离 /* 寻找最短路径用了floyd算法的原理,求两个点之前的最短距离,不断寻找中间点来缩小权值; 状态转移:遍历所有的三进制状态,找到上一个状态(第j个城市没去过的或者去过一次的)然后转移到这个状态j位置上加一的状态上,但是能不能转移 要看本次转移是不是会缩短时间 */ int main() { //freopen("in.txt","r",stdin); for(int i=0;i<59050;i++) { int x=i; for(int j=1;j<=10;j++)//最多有十位 { dis[i][j]=x%3; x/=3; if(x==0) break; //cout<<j<<endl; } //cout<<i<<endl; }//初始化第i个状态的j位上的数是几 while(scanf("%d%d",&n,&m)!=EOF) { int a,b,c; memset(g,INF,sizeof g); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); if(c<g[a][b]) g[a][b]=g[b][a]=c; }//处理输入 memset(dp,INF,sizeof dp); int tol=pow(3.0,n); for(int i=1;i<=n;i++) dp[state[i]][i]=0;//初始化从最后到达i城市最小距离的这个状态转移到i城市需要的最小时间就是0; int cur=INF; //下面求最短路径的原理是floyd算法(两个点之间不断寻找中间点来缩小权值) for(int i=0;i<tol;i++)//枚举所有可能的状态 { int flag=1;;//用于判断当前状态是不是没走 for(int j=1;j<=n;j++)//枚举你需要找的中间过程的城市 { if(dis[i][j]==0) flag=0;//判断这个是不是 if(dp[i][j]==INF) continue; //cout<<"dis[i][j]="<<dis[i][j]<<endl; for(int k=1;k<=n;k++)//枚举当前当前状态(就是你要转移到的状态) { if(j==k) continue; // cout<<"come in"<<endl; if(g[j][k]!=INF&&dis[i][k]<2)//从j到k的道路是通的,并且在这个状态中k点经过的次数不到两次 { int newstate=i+state[k];//新的状态就是走到这个城市,给k点经过的次数加一 dp[newstate][k]=min(dp[newstate][k],dp[i][j]+g[j][k]); } // cout<<"dp[newstate][k]="<<dp[newstate][k]<<endl; } //cout<<j<<endl; } if(flag) for(int j=1;j<=n;j++) cur=min(dp[i][j],cur); } if(cur==INF)//如果取到正无穷就是那么没有联通路所以就不可能走完 puts("-1"); else printf("%d\n",cur); } return 0; }
标签:
原文地址:http://www.cnblogs.com/wuwangchuxin0924/p/5744184.html