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;
    }
}

  

原文地址:https://www.cnblogs.com/zcb123456789/p/13674356.html