首页 > 代码库 > HDU 3001 Travelling 状态压缩dp+3进制
HDU 3001 Travelling 状态压缩dp+3进制
题意:一个人要旅行,他要去n个地方,且这n个地方每个地方最多可以走2次;
给m条路径,寻问最短花费
很明显的状态压缩,但是要求每个点最多只能走两次,就没办法标记当前点走过或是没走过,只能用三进制来表示
1代表地点1被走过一次、
2代表地点1被走过两次、
3(即10)代表地点2被走过一次、
4(即11)代表地点1被走过一次,地点2被走过一次、
5(即12)代表地点1被走过两次,地点2被走过一次、
附AC代码
#include<stdio.h> #include<string.h> int dis[15],dp[80000][15],dpp[80000][15]; int map[15][15]; int min1(int a,int b) { if(a<b) return a; return b; } int main() { int i,j,n,m,k; j=1; for(i=1;i<=11;i++) { dis[i]=j; j*=3; } for(i=0;i<dis[11];i++) { k=i; for(j=1;j<=11;j++) { dpp[i][j]=k%3; k/=3; } } while(scanf("%d%d",&n,&m)!=EOF) { int sum; memset(map,127,sizeof(map)); sum=map[0][0]; int cnt=map[0][0]; while(m--) { scanf("%d%d%d",&i,&j,&k); if(k<map[i][j])//重边 map[j][i]=map[i][j]=k; } memset(dp,127,sizeof(dp)); for(i=1;i<=n;i++) { dp[dis[i]][i]=0;// } for(k=0;k<dis[n+1];k++) { int tot=1; for(i=1;i<=n;i++) { if(dpp[k][i]==0) tot=0; if(dp[k][i]==cnt)continue; for(j=1;j<=n;j++) { if(i==j)continue;//相同的地点不用更新 if(dpp[k][j]>=2)continue;//两次不用更新,因为不能再走了 if(map[i][j]==cnt)continue;//map[i][j]==cnt表示没有从i到j的路故不用更新 int l=k+dis[j]; dp[l][j]=min1(dp[l][j],dp[k][i]+map[i][j]); } } if(tot) { for(i=1;i<=n;i++) { sum=min1(sum,dp[k][i]); } } } if(sum==cnt) sum=-1; printf("%d\n",sum); } return 0; }
HDU 3001 Travelling 状态压缩dp+3进制
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。