题目链接:https://vjudge.net/problem/HDU-3001
题意:有n个城市,m条道路,你的起点城市任意,每个城市最多走两遍,问你走完n的城市的最短路是多少,如果走不完n个城市就输出-1.
思路:虽然n最大为10,但每个城市有三种状态,走过0,1,2次。而且是多组输入,直接dfs暴力的话就会超时。所以我们可以用三进制来压缩状态,表示去过的次数。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; int a[215][15],b[20],c[15][60005]; int n; int solve(int wei[],int state)//求出状态state下已经到达过的城市的数量 { int sum=0; for(int i=0; i<n; i++) { wei[i]=state%3; state/=3; if(wei[i]) sum++; } return sum; } int main() { int m; b[0]=1; for(int i=1; i<=10; i++) b[i]=b[i-1]*3; while(~scanf("%d%d",&n,&m)) { memset(a,-1,sizeof(a)); memset(c,INF,sizeof(c)); for(int i=1; i<=m; i++) { int x,y,z; cin>>x>>y>>z; x--,y--; if(a[x][y]==-1) a[x][y]=a[y][x]=z; else a[x][y]=a[y][x]=min(a[x][y],z); } int ans=INF; for(int state=1; state<b[n]; state++) //枚举状态state { int wei[12]; int sum=solve(wei,state); for(int i=0; i<n; i++)//枚举此时所在城市 { if(wei[i]==0) continue; if(sum==1) c[i][state]=0; if(c[i][state]==-1) continue; if(sum==n)//已经将所有城市玩过 ans=min(ans,c[i][state]); for(int j=0; j<n; j++) //枚举下一个去的城市 { if(i!=j&&wei[j]<2&&a[i][j]!=-1) { int nex=state+b[j]; c[j][nex]=min(c[j][nex],c[i][state]+a[i][j]); } } } } if(ans==INF) cout<<"-1"<<endl; else cout<<ans<<endl; } }