hdu 3681 Prison Break
http://acm.hdu.edu.cn/showproblem.php?pid=3681
题意:一个n*m的矩阵,'F'是起点。机器人从F出发,走到G可以充电,走到Y关掉开关,D不能走进,要求把所有开关关掉,且电量最少,并求出该最小电量。
把F,G,Y的坐标存起来,然后用bfs求出它们每两个点最短距离,然后用dp判断是不是可以满足目的状态。 用二分枚举答案。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <algorithm> 5 #define maxn 17 6 using namespace std; 7 const int inf=1<<29; 8 9 char g[16][16]; 10 int n,m; 11 int gg[16][16]; 12 bool vis[16][16]; 13 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 14 int sx,sy; 15 int spos; 16 int epos; 17 int cnt; 18 int dis[16][16]; 19 int dp[(1<<maxn)][maxn]; 20 struct node 21 { 22 int x,y; 23 }p[16],st,st1,st2; 24 25 int bfs(int s,int t) 26 { 27 queue<node>q; 28 memset(vis,false,sizeof(vis)); 29 for(int i=0; i<n; i++) 30 { 31 for(int j=0; j<m; j++) 32 { 33 dis[i][j]=inf; 34 } 35 } 36 dis[p[s].x][p[s].y]=0; 37 st.x=p[s].x; 38 st.y=p[s].y; 39 vis[p[s].x][p[s].y]=true; 40 q.push(st); 41 while(!q.empty()) 42 { 43 st1=q.front(); 44 q.pop(); 45 if(st1.x==p[t].x&&st1.y==p[t].y) 46 { 47 return dis[st1.x][st1.y]; 48 } 49 for(int i=0; i<4; i++) 50 { 51 int xx=st1.x+dir[i][0]; 52 int yy=st1.y+dir[i][1]; 53 if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&g[xx][yy]!='D') 54 { 55 dis[xx][yy]=dis[st1.x][st1.y]+1; 56 st2.x=xx; 57 st2.y=yy; 58 vis[xx][yy]=true; 59 q.push(st2); 60 } 61 } 62 } 63 return -1; 64 } 65 66 int ok(int c) 67 { 68 memset(dp,-1,sizeof(dp)); 69 dp[1<<spos][spos]=c; 70 for(int i=0; i<(1<<cnt); i++) 71 { 72 for(int j=0; j<cnt; j++) 73 { 74 if((i&(1<<j))==0) continue; 75 if(dp[i][j]==-1) continue; 76 if((i&epos)==epos) return true; 77 for(int k=0; k<cnt; k++) 78 { 79 if(i&(1<<k)) continue; 80 if(gg[j][k]==-1) continue; 81 if(dp[i][j]<gg[j][k]) continue; 82 if(dp[i|(1<<k)][k]==-1) dp[i|(1<<k)][k]=dp[i][j]-gg[j][k]; 83 else dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]-gg[j][k]); 84 int x1=p[k].x,y1=p[k].y; 85 if(g[x1][y1]=='G') dp[i|(1<<k)][k]=c; 86 } 87 } 88 } 89 return false; 90 } 91 92 int main() 93 { 94 while(scanf("%d%d",&n,&m)!=EOF) 95 { 96 if(n==0&&m==0) break; 97 cnt=0; 98 epos=0; 99 for(int i=0; i<n; i++) 100 { 101 scanf("%s",g[i]); 102 for(int j=0; j<m; j++) 103 { 104 if(g[i][j]=='F') 105 { 106 sx=i; sy=j; 107 spos=cnt; 108 epos|=(1<<cnt); 109 p[cnt].x=i; 110 p[cnt++].y=j; 111 } 112 if(g[i][j]=='G') 113 { 114 p[cnt].x=i; 115 p[cnt++].y=j; 116 } 117 if(g[i][j]=='Y') 118 { 119 epos|=(1<<cnt); 120 p[cnt].x=i; 121 p[cnt++].y=j; 122 } 123 } 124 } 125 for(int i=0; i<cnt; i++) 126 { 127 for(int j=0; j<cnt; j++) 128 { 129 if(i==j) gg[i][j]=0; 130 else gg[i][j]=bfs(i,j); 131 } 132 } 133 int l=0,r=n*m; 134 int mid; 135 int ans=-1; 136 while(l<=r) 137 { 138 mid=(l+r)>>1; 139 if(ok(mid)) 140 { 141 ans=mid; 142 r=mid-1; 143 } 144 else l=mid+1; 145 } 146 printf("%d\n",ans); 147 } 148 return 0; 149 }