1. 程式人生 > >HDU---Travelling(三進位制狀態壓縮)

HDU---Travelling(三進位制狀態壓縮)

題意:題意: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進位制化化十進位制)

詳細可見程式碼

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