HDU 3681 Prison Break (二分答案+状压DP+bfs预处理)
来源:互联网 发布:佳能e618清零软件 编辑:程序博客网 时间:2024/05/17 07:47
题意:
机器人从F出发,走到G可以充满电,走到Y关掉开关,D不能走进,要求把所有开关关掉,且机器人存储的电量最少,并求出该最小电量。
分析:
把F,G,Y三种类型的点找出来,进行讨论,首先bfs处理出来各个点之间的最短路。现在题目就变成了:求一幅图中满足走遍所有Y点的条件,机器人存储的电量最少。
由于点最多只有15个,状压dp来处理。二分机器人的储电量,每次用dp来做判定条件。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;int n,m;char map[22][22];int dist[22][22],vis[22][22];int dx[] = {0,0,-1,1};int dy[] = {1,-1,0,0};int dp[22][1<<16];struct node { int x,y,step; char c;}q[1111],p[20];int head,tail,cnt,st,numY;int bfs(int x,int y,int xx,int yy) { head = 0; tail = 0; memset(vis,0,sizeof(vis)); q[head].x = x; q[head].y = y; q[head++].step = 0; vis[x][y] = 1; while(head != tail) { node t = q[tail++]; node tt; if(t.x == xx && t.y == yy) { return t.step; } for(int i=0; i<4; i++) { tt.x = t.x + dx[i]; tt.y = t.y + dy[i]; if(tt.x<0 || tt.x>=n || tt.y<0 || tt.y >=m || map[tt.x][tt.y] == 'D' || vis[tt.x][tt.y] ) continue; tt.step = t.step + 1; vis[tt.x][tt.y] = 1; q[head++] = tt; } } return -1;}void getdist() { for(int i=0; i<cnt; i++) { for(int j=i; j<cnt; j++) { if(i == j) dist[i][j] = 0; else { dist[i][j] = bfs(p[i].x,p[i].y,p[j].x,p[j].y); dist[j][i] = dist[i][j]; } } }}int getY(int x) { int id = 0; int num = 0; while(x) { if((x & 1) && p[id].c == 'Y') num ++; x = x >> 1; id ++; } return num;}int judge(int va) { memset(dp,-1,sizeof(dp)); int total = 1 << cnt; dp[st][1 << st] = va; for(int j=0; j<total; j++) { if((j & (1 << st)) == 0) continue; for(int i=0; i<cnt; i++) { if(i == st) continue; for(int k=0; k<cnt; k++) { if(dist[i][k] == -1) continue; if(dist[i][k] <= dp[k][j ^ (1 << i)]) { if(p[i].c == 'G') dp[i][j] = va; else dp[i][j] = max(dp[i][j],dp[k][j ^ (1 << i)] - dist[i][k]); } } } } for(int j=0; j<total; j++) { if((j & (1 << st)) == 0) continue; if(getY(j) == numY) { for(int i=0; i<cnt; i++) { if(p[i].c == 'Y' && dp[i][j] != -1) return 1; } } } return 0;}void solve() { getdist(); int l = 1, r = 250, mid; int minn = 251; while(l <= r) { mid = (l + r) >> 1; if(judge(mid)) { minn = min(minn,mid); r = mid - 1; } else l = mid + 1; } if(minn == 251) puts("-1"); else printf("%d\n",minn);}int main() { while(scanf("%d%d",&n,&m)) { if(n == 0 && m == 0) break; cnt = 0; numY = 0; for(int i=0; i<n; i++) scanf("%s",map[i]); for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(map[i][j] == 'F') { p[cnt].x = i; p[cnt].y = j; p[cnt].c = 'F'; st = cnt; cnt ++; } if(map[i][j] == 'G') { p[cnt].x = i; p[cnt].y = j; p[cnt].c = 'G'; cnt++; } if(map[i][j] == 'Y') { numY ++; p[cnt].x = i; p[cnt].y = j; p[cnt].c = 'Y'; cnt++; } } } solve(); } return 0;}
- HDU 3681 Prison Break (二分答案+状压DP+bfs预处理)
- hdu 3681 Prison Break bfs+二分+dp
- HDU-3681-Prison Break(BFS+状压DP+二分)
- HDU 3681 Prison Break(bfs+二分+状压DP)
- HDU 3681-Prison Break(状压DP+二分+BFS)
- HDU 3681 Prison Break (状压DP+二分)
- hdu 3681 Prison Break(状压dp+二分)
- HDU 3681Prison Break(BFS+二分+状态压缩DP)
- hdu 3681 Prison Break bfs + 二分 + TSP
- HDU-3681 Prison Break (bfs + 二分枚举)
- 【HDU3681】Prison Break-状态压缩DP+BFS+二分答案
- HDU 3681 Prison Break(状压DP + 二分)
- HDU 3861 Prison Breake 状态压缩dp+BFS+二分答案
- hdu 3681 Prison Break (BFS+状压)
- HDOJ 3681 Prison Break BFS+状态压缩dp+二分
- HDU3681 Prison Break(壮压dp+二分+bfs)
- HDU 3681 Prison Break floyd+状压+二分
- HDU 3681 Prison Break (搜索+状压dp)
- _ALIGN宏与内存对齐
- Weblogic 验证码无法显示错误解决办法
- 锂电池保护板原理
- 实时性Hadoop
- UVA 590 Always on the run
- HDU 3681 Prison Break (二分答案+状压DP+bfs预处理)
- Tomcat集群配置
- c# 读取 Excel的内容
- poj 3648 2-SAT建图+topsort输出结果
- Select()系统调用及文件描述符集fd_set的应用
- javascript和c++的语法不同之处整理
- C语言的定义与声明
- libpcap中<pcap.h>中定义的函数
- SilkTest入门快打1-录制回放