首页 > 代码库 > UVA 10944 Nuts for nuts 经典状压DP
UVA 10944 Nuts for nuts 经典状压DP
https://vjudge.net/problem/UVA-10944
//题意:给出n*m地图,起点为L,每次可以向8个方向移动,地图中有若干个果实,求搜集所有果实后再回到起点的最短路径
//n,m<=20,果实个数<=15 则容易用二进制记录当前拿到的果实
//设dp[i][state]为当前s在果实i&&拿到的果实状态为state
//当2^(i-1) & j==0时,dp[i][j+2^(i-1)]=min(dp[i][j+2^(i-1)],dp[k][j]+dist(k,i)) 按状态增大方向递推即可
#include <bits/stdc++.h> using namespace std; const int N=40; const int inf=1<<20; const int M=5e6; char s[N]; int num,n,m,dist[N][N],x[N],y[N];// int dp[N][M]; void init() { for(int i=0;i<=num;i++) for(int j=i;j<=num;j++) dist[i][j]=dist[j][i]=max(abs(x[i]-x[j]),abs(y[i]-y[j]));//可以走8方向 } int main() { while(scanf("%d%d",&n,&m)!=EOF) { num=0; for(int i=0;i<n;i++) { scanf("%s",s); for(int j=0;j<m;j++) { if(s[j]==‘L‘) { x[0]=i; y[0]=j; } else if(s[j]==‘#‘) { x[++num]=i; y[num]=j; } } } if(!num) { puts("0"); continue; } init();//计算果实间距离 int state=(1<<num)-1; memset(dp,0x7f,sizeof(dp)); for(int i=1;i<=num;i++) dp[i][1<<(i-1)]=dist[0][i]; //O(15*15*2^15) for(int i=0;i<state;i++) { for(int j=1;j<=num;j++)//枚举当前最后一个搜集到的果实 { if(i&(1<<(j-1))) for(int k=1;k<=num;k++)//枚举最后一个以外过时k { if(!(i&(1<<(k-1)))) dp[k][i+(1<<(k-1))]=min(dp[k][i+(1<<(k-1))],dp[j][i]+dist[j][k]); } } } int ans=inf; for(int i=1;i<=num;i++) ans=min(ans,dp[i][state]+dist[i][0]); printf("%d\n",ans); } return 0; }
UVA 10944 Nuts for nuts 经典状压DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。