HDU 3681 二分+状压+BFS
来源:互联网 发布:alias vred软件下载 编辑:程序博客网 时间:2024/06/08 04:29
题意
一个人要出逃,需要从F点出发,访问所有的Y点才可以成功出逃,这个人可以拥有一个能量为V的背包,每移动一格消耗1点能量,到达G点的时候可以补充满能量。问最少需要携带一个多小的背包,才能成功出逃。
题解
第一眼看见这道题的时候,想的只是一个普通的BFS。但是在用优先队列实现的时候出现了一些问题,不太好判断优先访问哪个点。倘若不进行优先访问的选择,允许重复访问同一个点,那么无论是时间上还是空间上都是不可承受的。
看了题解才意识到这道题不是一道普通的BFS题,ORZ。。二分背包容量,BFS计算两点之间最短路,状压DP计算某个背包容量是否可行。
代码
#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define INF 0x3f3f3f3f#define LL long long#define MAXN 8200#define EPS 1e-10#define MOD 100000000using namespace std;struct Node { int x,y;};char mp[20][20];int vis[20][20];int dis[20][20][20][20];int dp[20][67000];int nodenum;int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};Node nodes[20];int n,m;int finalState;int start;void bfs(int x,int y) { memset(vis,false,sizeof(vis)); queue<Node> que; Node first; first.x=x; first.y=y; que.push(first); dis[first.x][first.y][first.x][first.y]=0; W(!que.empty()) { Node front=que.front(); que.pop(); vis[front.x][front.y]=true; UP(i,0,4) { Node newnode=front; newnode.x+=dir[i][0]; newnode.y+=dir[i][1]; if(newnode.x>=n||newnode.y>=m||newnode.x<0||newnode.y<0) continue; if(vis[newnode.x][newnode.y]) continue; if(mp[newnode.x][newnode.y]=='D') continue; dis[newnode.x][newnode.y][x][y]=dis[front.x][front.y][x][y]+1; que.push(newnode); } }}bool check(int v) { memset(dp,-1,sizeof(dp)); dp[start][1<<start]=v; UP(k,0,1<<nodenum) { UP(i,0,nodenum) { if(dp[i][k]==-1||!(k&(1<<i))) continue; if((k&finalState)==finalState) return true; UP(j,0,nodenum) { if(i==j||(k&(1<<j))) continue; int cost=dis[nodes[i].x][nodes[i].y][nodes[j].x][nodes[j].y]; if(cost==-1||cost>dp[i][k]) continue; dp[j][k+(1<<j)]=max(dp[j][k+(1<<j)],dp[i][k]-cost); if(mp[nodes[j].x][nodes[j].y]=='G') dp[j][k+(1<<j)]=v; } } } return false;}int main() { W(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; memset(dis,-1,sizeof(dis)); nodenum=0; finalState=0; UP(i,0,n) { scanf("%s",mp[i]); UP(j,0,m) { if(mp[i][j]=='F') { start=nodenum; finalState+=(1<<nodenum); nodes[nodenum].x=i; nodes[nodenum++].y=j; } if(mp[i][j]=='Y') { finalState+=(1<<nodenum); nodes[nodenum].x=i; nodes[nodenum++].y=j; } if(mp[i][j]=='G') { nodes[nodenum].x=i; nodes[nodenum++].y=j; } } } UP(i,0,nodenum) { bfs(nodes[i].x,nodes[i].y); } int left=0,right=250; int ans=INF; W(left<=right) { int mid=(left+right)/2; if(check(mid)) { right=mid-1; ans=min(ans,mid); } else { left=mid+1; } } if(ans==INF) { puts("-1"); } else { printf("%d\n",ans); } }}/*5 5GDDDSSSDFDSYGDSSGGYSSSYSS1 4FYGY*/
阅读全文
0 0
- HDU 3681 二分+状压+BFS
- hdu 3681(bfs+二分+状压dp判断)
- HDU 3681 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+二分+BFS)
- hdu 3681 Prison Break bfs+二分+dp
- hdu 3681 二分+状态压缩dp+bfs
- hdu 3681 Prison Break bfs + 二分 + TSP
- HDU-3681 Prison Break (bfs + 二分枚举)
- HDU 5652 (二分 bfs)
- HDU 3468 BFS + 二分匹配
- HDU 3681Prison Break(BFS+二分+状态压缩DP)
- hdu3681 状压 bfs 二分
- hdu 5179(bfs打表+二分)
- HDU 3468 双bfs+二分图
- HDU 5652 二分+并查集+BFS
- 从零开始构建支持TLS1.2的Web服务器Linux版(二) 配置Tomcat环境
- 0037_Sudoku Solver
- sudo
- 搭建spring boot整合mybatis环境
- 我所知道的HTTP和HTTPS
- HDU 3681 二分+状压+BFS
- 如何判断一个数是否为4的幂次方?若是,并判断出来是多少次方?
- Leetcode_215_Kth Largest Element in an Array
- Map、list、set方法使用总结
- 最优分解问题 (intDiv.cpp)
- SQL知识点总结
- 手写JavaScript模板引擎
- Python学习笔记
- z-index,标签之间的嵌套规则,精灵图,整站练习(css初始化)