Travelling
题目链接: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;
}
}
浙公网安备 33010602011771号