首页 > 代码库 > hdu3001Travelling (状态压缩DP,三进制)
hdu3001Travelling (状态压缩DP,三进制)
Travelling
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3611 Accepted Submission(s): 1132
Problem Description
After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn‘t want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.
Input
There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.
Output
Output the minimum fee that he should pay,or -1 if he can‘t find such a route.
Sample Input
2 1 1 2 100 3 2 1 2 40 2 3 50 3 3 1 2 3 1 3 4 2 3 10
Sample Output
100 90 7
Source
2009 Multi-University Training Contest 11 - Host by HRBEU
由于本题中一个点最多能够访问2次,由此可以联想到3进制;
dp[j][i]表示在状态i下到达终点j走过的最小的路程。具体下面的代码中有解释。
#include<stdio.h> int map[12][12],n,dp[12][60000];//dp[i][state]表示state状态以i点结尾的最小路径 int Min(int a,int b) { return a>b?b:a; } int toArray(int three[],int sum) { int k=0; for(int i=0;i<n;i++) { three[i]=sum%3; sum/=3; if(three[i])k++; } return k;//在状态sum中有k个点己经走过 } int main() { int m,a,b,c,in[12],MIN,three[12],k; in[0]=1; for(int i=1;i<=10;i++)in[i]=in[i-1]*3; //3的i次方 while(scanf("%d%d",&n,&m)==2) { for(int i=0;i<n;i++)//初始化 { for(int j=0;j<in[n];j++) dp[i][j]=-1; for(int j=0;j<n;j++) map[i][j]=-1; } while(m--) { scanf("%d%d%d",&a,&b,&c); a--; b--; if(map[a][b]!=-1)//判重 map[a][b]=map[b][a]=Min(map[a][b],c); else map[a][b]=map[b][a]=c; } MIN=-1; for(int Go=1;Go<in[n];Go++)//枚举己走的状态Go { k=toArray(three,Go); for(int i=0;i<n;i++) if(three[i])//状态Go以点i结尾时 { if(k==1)//只有一个点 dp[i][Go]=0; if(dp[i][Go]==-1)continue;//状态Go不能以点i为结尾点 if(k==n)//n个点己经走过 { if(MIN==-1)MIN=dp[i][Go]; else MIN=Min(MIN,dp[i][Go]); } for(int j=0;j<n;j++)//找个点j,从i点走到j点,状态tGo以j点结尾 if(i!=j&&three[j]<2&&map[i][j]!=-1) { int tGo=Go+in[j]; if(dp[j][tGo]==-1) dp[j][tGo]=dp[i][Go]+map[i][j]; else dp[j][tGo]=Min(dp[i][Go]+map[i][j],dp[j][tGo]); } } } printf("%d\n",MIN); } }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。