题意:Ignatius 被困在迷宫里,他必须在6分钟之内逃出去,否则就会被安装在其中的倒计时已剩6分钟的炸弹炸死。给出迷宫的布局:0 代表墙,不能通过。1 代表路,可以通过。2 Ignatius 的起始位置。3 出口位置。4 炸弹重置装置,可以使炸弹倒计时剩余时间重置为6分钟。问 Ignatius 能否逃出迷宫,如能输出最下时间,否则输出-1。
分析:优先队列。有一个二维数组stepsum[][]记录上次转移到这个位置的状态(时间花费,炸弹爆炸剩余时间)。从一个状态能否转移到当前点(x,y)要满足几个条件:1.该位置可走(非0) 2.剩余时间>0 3.转移到该点后的状态要比之前转移到这个状态要好(就是更有可能逃出迷宫)。 还有一点是一旦转移到 4炸弹重置装置 的位置,这个炸弹重置装置就相当于报废了。为什么?因为下次转移到这个点的时候不可能比第一次转移到该点之后的状态更优了。
Code:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int maxn=10; const int inf=0x3f3f3f3f; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int maze[maxn][maxn]; struct Node{ int cost,res; }stepsum[maxn][maxn]; struct node{ int x,y,cost,res; node(int xx,int yy,int cc,int rr):x(xx),y(yy),cost(cc),res(rr){} bool friend operator <(node a,node b){ return a.cost>b.cost; } }; int n,m,sx,sy,ex,ey; void Init(){ scanf("%d %d",&n,&m); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ scanf("%d",&maze[i][j]); if(maze[i][j]==2) sx=i,sy=j; else if(maze[i][j]==3) ex=i,ey=j; stepsum[i][j].cost=inf; stepsum[i][j].res=-1; } } } bool OK(int x,int y){ if(x>=0&&x<n&&y>=0&y<m&&(maze[x][y]!=0)) return true; return false; } int bfs(){ priority_queue<node>Q; Q.push(node(sx,sy,0,6)); while(!Q.empty()){ node cur=Q.top(); Q.pop(); if((cur.x==ex)&&(cur.y==ey)&&(cur.res>0)) return cur.cost; for(int i=0;i<4;i++){ int tx=cur.x+dir[i][0]; int ty=cur.y+dir[i][1]; int tc=cur.cost+1; int tr=cur.res-1; if(tr<=0) continue; if(OK(tx,ty)){ if(maze[tx][ty]==4) {tr=6;maze[tx][ty]=5;} if((tr>=stepsum[tx][ty].res)||(tc<=stepsum[tx][ty].cost)){ stepsum[tx][ty].cost=tc; stepsum[tx][ty].res=tr; Q.push(node(tx,ty,tc,tr)); } } } } return -1; } int main() { int cas; scanf("%d",&cas); while(cas--){ Init(); printf("%d\n",bfs()); } return 0; }