HDU---Travelling(三进制状态压缩)

https://vjudge.net/problem/HDU-3001

题意:题意:Mr ACMer想要进行一次旅行,他决定访问n座城市。Mr ACMer 可以从任意城市出发,必须访问所有的城市至少一次,并且任何一个城市访问的次数不能超过2次。n座城市间有m条道路,每条道路都有一个费用。求Mr ACMer 完成旅行需要花费的最小费用。如果不能完成旅行,则输出-1。

思路:每个点最多只能被访问2次,用3进制来压缩状态,0,1,2分别表示走该点0,1,2次.要注意枚举点的时候,路径和点的对应关系.

假设有3个城市 1 1 0表示前2个城市被访问了1次,第3个城市还没被访问,化成十进制就是12(这里是3进制化化十进制)

详细可见代码

与该题https://blog.csdn.net/qq_38924883/article/details/82987663 有类似之处。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int dp[60000][12];
int cost[12][12];
int three[12];
int digit[60000][12];///digit[i][j]表示状态为i,第j为是多少(0,1,2),也就是在状态i下,从第1个城/
市到第10个城市分别被访问了几次,这里n最多只能取到10;
void init()
{
    three[0]=1;
    for(int i=1;i<=10;i++)
        three[i]=three[i-1]*3;
    for(int i=0;i<three[10];i++)
    {
        int temp=i;
        for(int j=0;j<10;j++)
        {
            digit[i][j]=temp%3;
            temp/=3;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    init();
    int n,m;
    while(cin>>n>>m)
    {
        memset(cost,inf,sizeof(cost));
        for(int i=0;i<three[n];i++)
            for(int j=0;j<n;j++)
            dp[i][j]=inf;
        while(m--)
        {
            int u,v,w;
            cin>>u>>v>>w;
            cost[u-1][v-1]=cost[v-1][u-1]=min(cost[u-1][v-1],w);
        }

        for(int i=0;i<n;i++)
            dp[three[i]][i]=0;
         ///dp[i][j]的意思为 在状态i下,最后走到的城市为第j个城市.

        int ans=inf;
        for(int i=0;i<three[n];i++)///枚举状态
        {
            bool flag=1;
            for(int j=0;j<n;j++)///枚举最后到达的城市
            {
                if(digit[i][j]==0) flag=0;///如果最后到达的城市是走过的话那么就可以更新一次答案
                if(dp[i][j]!=inf)///保证是从起点出发
                for(int k=0;k<n;k++)
                    if(cost[j][k]!=inf&&digit[i][k]!=2)///j到k之间是有路的,而且k城市没有被访问2次
                    {
                        dp[i+three[k]][k]=min(dp[i+three[k]][k],dp[i][j]+cost[j][k]);
                       ///最后访问的城市就变成了k
                    }
            }
            if(flag)
            {
                for(int j=0;j<n;j++)
                    ans=min(ans,dp[i][j]);
            }
        }
        if(ans>=inf) cout<<-1<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38924883/article/details/82987302