首页 > 代码库 > HDU 3001 Travelling 状压DP
HDU 3001 Travelling 状压DP
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001
题意:还是环游地图的问题,只不过这回旅行者对自己有着严格的要求,地图上每个点的经过次数不能超过两次。
思路:依然是状压DP问题,根上一道很像,只不过这次对于每个点来说有三种状态,分别是未经过,经过一次,经过两次。所以要用三进制的数来进行状态压缩,这个关键点想明白了其他的和上一道基本一样了。对于我来说需要注意的是:能够到达某一个点经过了两次的状态的前一个状态是这个点已经经过了一次的状态,而不是从来未经过这个点的状态。
代码:
#include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <ctype.h> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #include <vector> #define eps 1e-8 #define INF (1<<30)-1 #define maxn 100005 #define PI acos(-1.0) #define seed 31//131,1313 typedef long long LL; typedef unsigned long long ULL; using namespace std; int Pow[15]; int cost[15][15]; int dp[59500][15]; void init() { for(int i=0; i<10; i++) { for(int j=0; j<59500; j++) dp[j][i]=INF; } Pow[0]=1; dp[Pow[0]][0]=0; for(int i=1; i<=10; i++) { Pow[i]=Pow[i-1]*3; dp[Pow[i]][i]=0; } for(int i=0; i<10; i++) for(int j=0; j<10; j++) cost[i][j]=INF; return ; } int main() { int n,m,k,pos; LL ans; while(~scanf("%d%d",&n,&m)) { init(); ans=INF; for(int i=0; i<m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(cost[x-1][y-1]>z) { cost[x-1][y-1]=z; cost[y-1][x-1]=z; } } for(int i=1; i<Pow[n]; i++) { k=i; pos=0; while(k) { if(k%3==1||k%3==2) { for(int ii=0; ii<n; ii++) { if(ii==pos) continue; if(dp[i-Pow[pos]][ii]+cost[ii][pos]<dp[i][pos]) dp[i][pos]=dp[i-Pow[pos]][ii]+cost[ii][pos]; } } k/=3; pos++; } } for(int i=1;i<Pow[n];i++) { bool flag=0; k=i; int t=0; while(k) { t++; if(k%3==0) flag=1; k/=3; } if(flag==0&&t==n) { for(int ii=0;ii<n;ii++) if(dp[i][ii]<ans) ans=dp[i][ii]; } } if(ans!=INF) printf("%I64d\n",ans); else puts("-1"); } return 0; }
HDU 3001 Travelling 状压DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。