保存现场的BFS-hdu-2128-Tempter of the Bone II
来源:互联网 发布:ibm云计算产品 编辑:程序博客网 时间:2024/06/05 21:49
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2128
题目意思:
在一个矩阵中,给一个起点一个终点,矩阵中有的位置有墙,有的位置有炸弹,对于墙必须拿炸弹炸才能过,每走一步花费1s,每炸一次门花1s,问从起点到终点的最短时间。
解题思路:
BFS。(DFS会超时)
因为地图会变,所以普通的BFS,不行。必须要保存现场,使得之前不能到达的路径对地图的改变能够还原,使得对后面的正确路径无影响。
又对于矩阵任意位置,要么可走(1),要么不可走(0)。所以可以用二进制来保存地图。对每一个点保存多个状态地图,map<ull,int>myp[70] myp[i][j]表示到达第i个点时,当前地图状态为j时的最小的步数。
对于某点某状态,如果之前已经访问了该点该地图状态下并且此时的步数更大,则不用访问此点。
否则还需访问。
用优先队列使得每次从步数最小的点开始访问。
对于判重状态,要深思熟虑,是否真正可行。
代码:
#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#define eps 1e-6#define INF 0x1f1f1f1f#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define ull unsigned long long//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;/*freopen("data.in","r",stdin);freopen("data.out","w",stdout);*/struct Node{ ull s; int bt,st,pos; friend bool operator <(Node a,Node b) { return a.st>b.st; }}ss;map<ull,int>myp[70]; //map[i][j]表示当前走到第i个格子,int n,m; //地图状态为j时,所用的最小时间int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};char save[70];priority_queue<Node>myq;void ispush(ull state,int pp,Node cur,int add,int a){ map<ull,int>::iterator it; it=myp[pp].find(state); // if(it!=myp[pp].end()&&cur.st+1>=(it->second)) //之前队列以访问了该点该状态且时间更少 return; //故退出,相当于判重剪枝,记忆化搜索 Node tmp; //对于炸弹、墙 要不同考虑 tmp.bt=cur.bt+a,tmp.pos=pp,tmp.s=state,tmp.st=cur.st+add; myp[pp][tmp.s]=tmp.st; myq.push(tmp);}int bfs(){ myq.push(ss); myp[ss.pos][ss.s]=0; while(!myq.empty()) { Node cur=myq.top(); myq.pop(); int x=cur.pos/m,y=cur.pos%m; //位置坐标 int xx,yy; for(int i=0;i<4;i++) { xx=x+dir[i][0],yy=y+dir[i][1]; //走一步 if(xx<0||xx>=n||yy<0||yy>=m) //走出去了,不行 continue; int t=xx*m+yy; if(save[t]=='D') //走到了跳出 return cur.st+1; if(cur.s&((ull)1<<t)) //可以走 ispush(cur.s,t,cur,1,0); else if(save[t]=='X') //有墙 { if(cur.bt) { ull tt=cur.s|((ull)1<<t); //强炸掉后就可以走 ispush(tt,t,cur,2,-1); } } else { ull tt=cur.s|((ull)1<<t); //炸弹拿了后可以走 ispush(tt,t,cur,1,save[t]-'0'); } } } return -1;}int main(){ while(scanf("%d%d",&n,&m)&&n+m) { ss.s=0; getchar(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { int t=i*m+j; scanf("%c",&save[t]); if(save[t]=='S') //可以走 ss.pos=t,ss.bt=0,ss.st=0,ss.s|=((ull)1<<t); else if(save[t]=='D'||save[t]=='.') ss.s|=((ull)1<<t); //可以走 } getchar(); } for(int i=0;i<n*m;i++) //初始化 myp[i].clear(); while(!myq.empty()) myq.pop(); int ans=bfs(); printf("%d\n",ans); } return 0;}
附上几组测试数据:
8 8
......XD
.XXXX..X
.XXXXX..
.XXXXXXX
.XXXXXXX
...4XXXX
XXXXXXX3
XXXXXXXS
38
6 5
S.XX1
X.1X1
XX.X.
XXXXX
XXXXX
XXXDX
17
6 6
S1XX3X
XXXXXX
2XXXXX
XXXXXX
XXXXXX
X1XDXX
29
5 6
S.XXXX
21..XX
XXXXXX
XXXXXX
3XXXDX
11
5 3
S..
1X.
XX.
...
XXD
6
- 保存现场的BFS-hdu-2128-Tempter of the Bone II
- HDU 2128Tempter of the Bone II(bfs + 保存每一步的图)
- HDU 2128 Tempter of the Bone II(BFS)
- HDU-2128 Tempter of the Bone II BFS
- HDU-2128-Tempter of the Bone II(BFS)
- 【搜索】 HDU 2128 Tempter of the Bone II BFS 状压
- HDU 2128 Tempter of the Bone II(BFS+状态压缩)
- HDU 2128 Tempter of the Bone II(BFS)
- hdu 2128 Tempter of the Bone II ( bfs+不好搞的判重 )
- HDU 2128 Tempter of the Bone II
- HDU 2128 Tempter of the Bone II
- HDU 2128 Tempter of the Bone II
- HDU 2128Tempter of the Bone II
- hdu 2128 Tempter of the Bone II
- hdu2128 Tempter of the Bone II (BFS)
- HDU2128 Tempter of the Bone II BFS
- Tempter of the Bone II(BFS)
- (HDU Tempter of the Bone II) BFS + 可捡炸弹炸墙的迷宫问题
- poj 1321 棋盘问题
- typedef 函数指针的用法
- Linux常用命令
- Forum Design in detail
- hdu1172(暴力枚举)
- 保存现场的BFS-hdu-2128-Tempter of the Bone II
- u-boot_smdkv210 分析六:内存分配
- Mac 软件清单
- (二十)职责链模式详解(都市异能版)
- 在桌面打不开可执行文件 (application/x-executable)的软链
- /dev/zero和/dev/null的区别
- JS的函数节流与函数去抖
- TCP的FIN、ACK、SYN、URG、PSH及攻击方式
- Discuz的下载及安装