HDU 3681 Prison Break 哈密顿回路DP
来源:互联网 发布:空中英语教室 知乎 编辑:程序博客网 时间:2024/05/18 20:08
题意是已知一幅矩阵迷宫,給起点,开始时充满电,要求是遍历给定的点,每移动一次花费1,迷宫中有若干充电池可充满电(每个充电池只能用一次),求原始电量最少是多少*/
首先抽象出起点、终点、充电池,建立他们的最短路径图,二分枚举原始电量 从而转化为 哈密尔顿回路的状态DP问题 。这样建图原理是:对于原图当前用不用充电池 在新图中 我们可以用两种不同的边来表示(在新图中通过一条边移动到一个充电池则一定用此充电池,而在边上经过充电池时不用)
BFS做法(用时421ms)
#include <cstdio>#include <cstring>#include <queue>using namespace std;struct Edge{ int v,next;}edge[2000];int head[300],cnt,ids,fin;int n,m;char map[20][20];int id[20][20];int c[20][2];int dis[20][20];struct Node{ int s,d;};void init(){ memset(head,-1,sizeof(head)); memset(id,-1,sizeof(id)); memset(dis,-1,sizeof(dis)); cnt=0,ids=1,fin=0;}void addedge(int u,int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;}void bfs(int s){ int i,j,u,v; struct Node tem,tem1; queue<struct Node>q; bool ok[400]; memset(ok,0,sizeof(ok)); tem.s=s,tem.d=0; q.push(tem); ok[s]=1; while(!q.empty()){ tem=q.front(); q.pop(); u=tem.s; if(id[u/m][u%m]!=-1) dis[id[s/m][s%m]][id[u/m][u%m]]=tem.d; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; if(ok[v])continue; ok[v]=1; tem1.s=v; tem1.d=tem.d+1; q.push(tem1); } }}int dp[1<<16][16];bool solve(int mid){ int i,j,k; memset(dp,-1,sizeof(dp)); dp[1][0]=mid; for(i=0;i<(1<<ids);i++) for(j=0;j<ids;j++){ if((i&(1<<j)==0) || dp[i][j]==-1)continue; if((i&fin)==fin) return 1; for(k=0;k<ids;k++){ if(i&(1<<k))continue; if(dis[k][j]==-1)continue; if(dp[i][j]>=dis[k][j]){ if(dp[i|(1<<k)][k]==-1 || dp[i|(1<<k)][k]<dp[i][j]-dis[k][j]) dp[i|(1<<k)][k]=dp[i][j]-dis[k][j]; if(map[c[k][0]][c[k][1]]=='G') dp[i|(1<<k)][k]=mid; } } } return 0;}int main(){ int i,j,k; while(scanf("%d %d",&n,&m) && n!=0 && m!=0){ init(); for(i=0;i<n;i++) scanf("%s",map[i]); for(i=0;i<n;i++) for(j=0;j<m;j++){ if(map[i][j]=='D')continue; if(map[i][j]=='F'){ c[0][0]=i; c[0][1]=j; id[i][j]=0; } else if(map[i][j]=='G'){ c[ids][0]=i; c[ids][1]=j; id[i][j]=ids++; } else if(map[i][j]=='Y'){ c[ids][0]=i; c[ids][1]=j; id[i][j]=ids++; fin|=(1<<(ids-1)); } if(i-1>=0 && map[i-1][j]!='D') addedge(i*m+j,(i-1)*m+j); if(i+1<n && map[i+1][j]!='D') addedge(i*m+j,(i+1)*m+j); if(j-1>=0 && map[i][j-1]!='D') addedge(i*m+j,i*m+j-1); if(j+1<m && map[i][j+1]!='D') addedge(i*m+j,i*m+j+1); } /*for(i=0;i<ids;i++){ for(j=0;j<ids;j++) printf("%d ",dis[i][j]); puts(""); } puts("");*/ for(i=0;i<ids;i++) bfs(c[i][0]*m+c[i][1]); int l=0,r=n*m*(ids-1),mid,ans=-1; while(l<=r){ int mid=(l+r)>>1; if(solve(mid)){ ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); } return 0;}
DFS做法(用时31ms)
#include <cstdio>#include <cstring>#include <queue>using namespace std;struct Edge{ int v,next;}edge[2000];int head[300],cnt,ids,fin,mid;int n,m;char map[20][20];int id[20][20];int c[20][2];int dis[20][20];struct Node{ int s,d;};void init(){ memset(head,-1,sizeof(head)); memset(id,-1,sizeof(id)); memset(dis,-1,sizeof(dis)); cnt=0,ids=1,fin=0;}void addedge(int u,int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;}void bfs(int s){ int i,j,u,v; struct Node tem,tem1; queue<struct Node>q; bool ok[400]; memset(ok,0,sizeof(ok)); tem.s=s,tem.d=0; q.push(tem); ok[s]=1; while(!q.empty()){ tem=q.front(); q.pop(); u=tem.s; if(id[u/m][u%m]!=-1) dis[id[s/m][s%m]][id[u/m][u%m]]=tem.d; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; if(ok[v])continue; ok[v]=1; tem1.s=v; tem1.d=tem.d+1; q.push(tem1); } }}int has[20];int dfs(int pos,int len,int sta){ if((sta&fin)==fin)return 1; for(int i=0;i<ids;i++){ if(has[i] || dis[pos][i]==-1)continue; if(len>=dis[pos][i]){ if(map[c[i][0]][c[i][1]]=='G'){ has[i]=1; if(dfs(i,mid,sta|(1<<i)))return 1; has[i]=0; } else{ has[i]=1; if(dfs(i,len-dis[pos][i],sta|(1<<i)))return 1; has[i]=0; } } } return 0;}int main(){ int i,j,k; while(scanf("%d %d",&n,&m) && n!=0 && m!=0){ init(); for(i=0;i<n;i++) scanf("%s",map[i]); for(i=0;i<n;i++) for(j=0;j<m;j++){ if(map[i][j]=='D')continue; if(map[i][j]=='F'){ c[0][0]=i; c[0][1]=j; id[i][j]=0; } else if(map[i][j]=='G'){ c[ids][0]=i; c[ids][1]=j; id[i][j]=ids++; } else if(map[i][j]=='Y'){ c[ids][0]=i; c[ids][1]=j; id[i][j]=ids++; fin|=(1<<(ids-1)); } if(i-1>=0 && map[i-1][j]!='D') addedge(i*m+j,(i-1)*m+j); if(i+1<n && map[i+1][j]!='D') addedge(i*m+j,(i+1)*m+j); if(j-1>=0 && map[i][j-1]!='D') addedge(i*m+j,i*m+j-1); if(j+1<m && map[i][j+1]!='D') addedge(i*m+j,i*m+j+1); } for(i=0;i<ids;i++) bfs(c[i][0]*m+c[i][1]); int flag=1; for(i=1;i<ids;i++){ if(map[c[i][0]][c[i][1]]=='Y') if(dis[0][i]==-1){ flag=0; break; } } int ans=-1; if(flag){ int l=0,r=n*m*(ids-1); while(l<=r){ mid=(l+r)>>1; memset(has,0,sizeof(has)); has[0]=1; if(dfs(0,mid,1)){ ans=mid; r=mid-1; } else l=mid+1; } } printf("%d\n",ans); } return 0;}
- HDU 3681 Prison Break 哈密顿回路DP
- hdu 3681 Prison Break bfs+二分+dp
- HDU 3681 Prison Break (搜索+状压dp)
- hdu 3681 Prison Break(dp || dfs)
- HDU 3681 Prison Break (状压DP+二分)
- 【搜索+状压DP】 HDU 3681 Prison Break
- HDU 3681 Prison Break - 状压dp【TSP】
- hdu 3681 Prison Break(状压dp+二分)
- 哈密顿回路,状态dp poj2288
- hdu3001(集合dp求哈密顿回路)
- 【例题】【图论(哈密顿回路)&DP(状压)】
- hdu 4337 (哈密顿回路模板)
- HDU 3681 - Prison Break
- HDU 3681 Prison Break
- HDU 3681Prison Break
- HDU 3681 Prison Break
- HDU 3681 Prison Break
- hdu 3681 Prison Break
- Historically Highest Index algorithm HH-index算法
- core文件调试
- java的设计模式
- 【PB】数据窗口技术
- STL 六大组件概述
- HDU 3681 Prison Break 哈密顿回路DP
- codeigniter单元测试
- 简单,方便,功能全的php分页类
- (转)maven环境快速搭建
- SQLPLUS使用介绍
- PCI总线操作四: PCI配置周期
- 指向指针的指针 指向数组的指针 指向指针的数组
- android退出提示框
- 去掉office标题前的黑点