hdu1885 Key Task
刚开始看到这题都吓到了,第一感觉就是不能记录已走过的点,一旦记录了,那假设钥匙在对面,门在这边,那拿完钥匙就回不来了;
可是,如果不记录的话,那岂不是在整个地图了乱窜,绝对超时,甚至是死循环;
之后,想了想,把每个点在入队列的时候,记录下状态每一个点的状态,即又有没有拿到钥匙,拿到哪几种钥匙之类的,如果回溯时,俩点的状态一样,则没必要入队,这确实是一种可行的办法,可是想到这里,突然,想到,要对每一个点保存16种状态,那内存肯定要爆了呀,结果思路就这么停了,想不出别的办法了……
查了一下,原来记录状态是用位运算保存呀,郁闷呐,亏我知道这东西存在,亏我还用过位运算保存过一个数字是否出现过,结果我居然一点都没想到,惭愧呀
是这样保存的,开一个三维的数组,flag[101][101][16],记录每一个点的状态,除了坐标之外,保存的是一个点有没有钥匙,有多少把钥匙,每一个位保存一把钥匙的状态,总共十六种状态
假设 // b,y,r, g 钥匙分别用二进制的第一,二,三,四位保存,flag&1 ==1 表示 该状态b钥匙已经有了,当拿到b钥匙时,flag|=1,记录下来。
#include<iostream> #include<queue> using namespace std; char map[101][101]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}},n,m; int flag[101][101][16]; // b,y,r, g: 1,2,4,8 struct node { int x,y,cnt,v; node(int _x=0,int _y=0,int _cnt=0 ,int _v=0):x(_x),y(_y),cnt(_cnt),v(_v){}; friend bool operator <(const node &a,const node &b) { return a.cnt>b.cnt; } }; node f; bool OK(int i,int j,int va) { if(map[i][j]=='B'&&(va&1)) return true; if(map[i][j]=='Y'&&(va&2)) return true; if(map[i][j]=='R'&&(va&4)) return true; if(map[i][j]=='G'&&(va&8)) return true; return false; } int bfs() { flag[f.x][f.y][f.v]=1; priority_queue<node> Q; Q.push(f); while(!Q.empty()) { node t=Q.top(); Q.pop(); for(int k=0;k<4;k++) { int i=t.x+dir[k][0]; int j=t.y+dir[k][1]; if(i<n&&i>=0&&j<m&&j>=0&&map[i][j]!='#') { if(OK(i,j,t.v)&&!flag[i][j][t.v]) { flag[i][j][t.v]=1; Q.push(node(i,j,t.cnt+1,t.v)); } else if(map[i][j]=='b'&&!flag[i][j][t.v|1]) { flag[i][j][t.v|1]=1; Q.push(node(i,j,t.cnt+1,t.v|1)); } else if(map[i][j]=='y'&&!flag[i][j][t.v|2]) { flag[i][j][t.v|2]=1; Q.push(node(i,j,t.cnt+1,t.v|2)); } else if(map[i][j]=='r'&&!flag[i][j][t.v|4]) { flag[i][j][t.v|4]=1; Q.push(node(i,j,t.cnt+1,t.v|4)); } else if(map[i][j]=='g'&&!flag[i][j][t.v|8]) { flag[i][j][t.v|8]=1; Q.push(node(i,j,t.cnt+1,t.v|8)); } else if(map[i][j]=='.'&&!flag[i][j][t.v]) { flag[i][j][t.v]=1; Q.push(node(i,j,t.cnt+1,t.v)); } else if(map[i][j]=='X') return t.cnt+1; } } } return 0; } int main() { while(cin>>n>>m&&(n||m)) { for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]=='*') f.x=i,f.y=j; } f.cnt=0;f.v=0;map[f.x][f.y]='.'; memset(flag,0,sizeof(flag)); int t=bfs(); if(t) cout<<"Escape possible in "<<t<<" steps."<<endl; else cout<<"The poor student is trapped!"<<endl; } return 0; }