HDU 3681 Prison Break (状压DP+二分)
来源:互联网 发布:温州淘宝运营培训学校 编辑:程序博客网 时间:2024/04/30 02:06
题意:给你一个n*m的图,机器人只能上下左右移动,移动一格消耗一点能量,F是起点,D是不可经过的点,S是空地,G是充能的站点,Y是必须经过的点,整个过程机器人必须让自己的能量尽可能的少,并且经过所有的Y,问机器人的最小能量容量是多少。
思路:因为‘G’和‘Y’的数量和T小于等于15,所以用这个来表示状态。
设'Y'的点数为Y。那么F标号为0,'Y'的点依次标号为1,2,....Y 。‘G’标号为Y+1,Y+2,....T。
状态S:第i位为1表示经过了第i-1个点。以此来二分答案。
设能量容量为k,dp[S][v]为经过状态S中的所有点,最后到达v的最大剩余能量。
状态转移方程:dp[S][v] = max(dp[S][v],dp[S-{v}][u] - G[u][v]) 如果dp[S][v] >= 0 且v > Y 的话,dp[S][v] = k。
我的代码:
#include<cstdio>#include<iostream>#include<map>#include<queue>#include<cstring>#include<algorithm>using namespace std;typedef pair<int,int> P;const int maxn = 15;const int inf = 0x3f3f3f3f;const int dx[4] = {1,-1,0,0};const int dy[4] = {0,0,1,-1};char maps[maxn][maxn];int n,m,T,G[maxn][maxn];int dp[1<<maxn][maxn];map<P,int> M;int Y;struct Nod{ int x,y,step;};bool vis[maxn][maxn];queue<Nod> que;void init(){ M.clear(); int tmp = 1 << maxn; //memset(G,-1,sizeof(G)); for(int i=0;i<maxn;i++) fill(G[i],G[i]+maxn,inf); //for(int i=0;i<tmp;i++) fill(dp[i],dp[i]+maxn,inf);}void bfs(int x,int y,int s){ //cout<<x<<" "<<y<<" "<<s<<endl; Nod cur,next; memset(vis,0,sizeof(vis)); cur.x = x;cur.y = y;cur.step = 0; que.push(cur); vis[x][y] = true; while(!que.empty()){ cur = que.front();que.pop(); //cout<<cur.x<<" "<<cur.y<<" "<<cur.step<<endl; if(cur.step > 0 && (maps[cur.x][cur.y] == 'G' || maps[cur.x][cur.y] == 'Y')){ int pos = M[P(cur.x,cur.y)]; G[s][pos] = cur.step; } for(int i=0;i<4;i++){ next.x = cur.x + dx[i]; next.y = cur.y + dy[i]; next.step = cur.step + 1; if(next.x < 0 || next.x >= n || next.y < 0 || next.y >= m || vis[next.x][next.y] || maps[next.x][next.y] == 'D') continue; vis[next.x][next.y] = true; que.push(next); } }}void build_graph(){ T = 1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maps[i][j] == 'Y') M.insert(make_pair(P(i,j),T++)); if(maps[i][j] == 'F') M.insert(make_pair(P(i,j),0)); } } Y = T - 1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maps[i][j] == 'G') M.insert(make_pair(P(i,j),T++)); } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maps[i][j] == 'F' || maps[i][j] == 'Y' || maps[i][j] == 'G'){ bfs(i,j,M[P(i,j)]); } } }}bool check(int S){ for(int i=0;i<Y;i++){ if(!(S >> i & 1)) return false; } return true;}bool binSearch(int k){ int Ed = 1 << T; bool flag; memset(dp,-1,sizeof(dp)); dp[0][0] = k; for(int S = 1; S < Ed ; S++){ flag = false; for(int v = 1; v <= T ; v++){ if(!(S >> (v - 1) & 1)) continue; int S0 = S - (1 << (v - 1)); if(S0 == 0){ dp[S][v] = max(dp[S][v],dp[0][0] - G[0][v]); } else{ for(int u = 1;u <= T;u++){ if(!(S0 >> (u - 1) & 1) || dp[S0][u] == -1) continue; dp[S][v] = max(dp[S][v],dp[S0][u] - G[u][v]); } } if(dp[S][v] >= 0){ flag = true; if(v > Y) dp[S][v] = k; } } if(check(S) && flag){ return true; } } return false;}void solve(){ T -= 1; int lb = 0,rb = 1000; while(rb - lb > 1){ int mid = (lb + rb) >> 1; if(binSearch(mid)) rb = mid; else lb = mid; } if(rb == 1000) printf("-1\n"); else printf("%d\n",rb);}int main(){ while(~scanf("%d%d",&n,&m)){ if(n + m == 0) break; init(); for(int i=0;i<n;i++) scanf("%s",maps[i]); build_graph(); solve(); } return 0;}
0 0
- HDU 3681 Prison Break (状压DP+二分)
- hdu 3681 Prison Break(状压dp+二分)
- hdu 3681 Prison Break bfs+二分+dp
- HDU 3681 Prison Break (二分答案+状压DP+bfs预处理)
- HDU-3681-Prison Break(BFS+状压DP+二分)
- HDU 3681 Prison Break(bfs+二分+状压DP)
- HDU 3681 Prison Break(状压DP + 二分)
- HDU 3681-Prison Break(状压DP+二分+BFS)
- HDU 3681 Prison Break floyd+状压+二分
- HDU 3681 Prison Break (搜索+状压dp)
- 【搜索+状压DP】 HDU 3681 Prison Break
- HDU 3681 Prison Break - 状压dp【TSP】
- HDU 3681Prison Break(BFS+二分+状态压缩DP)
- hdu 3681 Prison Break bfs + 二分 + TSP
- HDU-3681 Prison Break (bfs + 二分枚举)
- hdu 3681 Prison Break(dp || dfs)
- HDU 3681 - Prison Break
- HDU 3681 Prison Break
- c#第五次作业
- C#课程设计——“猜猜看”开发总结
- 选择法排序
- 只要关系配置正确,一条sql就可以解决循环中查询数据库的问题
- TCP/IP详解学习笔记——IP协议
- HDU 3681 Prison Break (状压DP+二分)
- Servlet--取得session,application内置对象
- mac 下面 you have an outdated version of /usr/bin/install_name_tool installed
- UISegmentControl/多段选择视图
- 怎么从Linux服务器上下载超过4G的文件?
- Android UI 组件开源软件
- 第三章(在线程间共享数据)
- Qt初学者,一路磕绊,将两天来心得发一下聊以遣怀。
- 【转】线程的7种状态及相互转换