Key Task
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2289 Accepted Submission(s): 1005
Total Submission(s): 2289 Accepted Submission(s): 1005
Problem Description
The Czech Technical University is rather old — you already know that it celebrates 300 years of its existence in 2007. Some of the university buildings are old as well. And the navigation in old buildings can sometimes be a little bit tricky, because of strange long corridors that fork and join at absolutely unexpected places.
The result is that some first-graders have often di?culties finding the right way to their classes. Therefore, the Student Union has developed a computer game to help the students to practice their orientation skills. The goal of the game is to find the way out of a labyrinth. Your task is to write a verification software that solves this game.
The labyrinth is a 2-dimensional grid of squares, each square is either free or filled with a wall. Some of the free squares may contain doors or keys. There are four di?erent types of keys and doors: blue, yellow, red, and green. Each key can open only doors of the same color.
You can move between adjacent free squares vertically or horizontally, diagonal movement is not allowed. You may not go across walls and you cannot leave the labyrinth area. If a square contains a door, you may go there only if you have stepped on a square with an appropriate key before.
The result is that some first-graders have often di?culties finding the right way to their classes. Therefore, the Student Union has developed a computer game to help the students to practice their orientation skills. The goal of the game is to find the way out of a labyrinth. Your task is to write a verification software that solves this game.
The labyrinth is a 2-dimensional grid of squares, each square is either free or filled with a wall. Some of the free squares may contain doors or keys. There are four di?erent types of keys and doors: blue, yellow, red, and green. Each key can open only doors of the same color.
You can move between adjacent free squares vertically or horizontally, diagonal movement is not allowed. You may not go across walls and you cannot leave the labyrinth area. If a square contains a door, you may go there only if you have stepped on a square with an appropriate key before.
Input
The input consists of several maps. Each map begins with a line containing two integer numbers R and C (1 ≤ R, C ≤ 100) specifying the map size. Then there are R lines each containing C characters. Each character is one of the following:
Note that it is allowed to have
- more than one exit,
- no exit at all,
- more doors and/or keys of the same color, and
- keys without corresponding doors and vice versa.
You may assume that the marker of your position (“*”) will appear exactly once in every map.
There is one blank line after each map. The input is terminated by two zeros in place of the map size.
OutputFor each map, print one line containing the sentence “Escape possible in S steps.”, where S is the smallest possible number of step to reach any of the exits. If no exit can be reached, output the string “The poor student is trapped!” instead.
One step is defined as a movement between two adjacent cells. Grabbing a key or unlocking a door does not count as a step.
Sample Input1 10 *........X 1 3 *#X 3 20 #################### #XY.gBr.*.Rb.G.GG.y# #################### 0 0
Sample OutputEscape possible in 9 steps. The poor student is trapped! Escape possible in 45 steps.
Source
Recommendlinle
题意:4种钥匙4种门,一类钥匙可以开这一类所有的门,求到达终点的最小步数刚开始是想创建一个六维数组保存没一种钥匙的状态,但是明显超内存了,自己还是太水了,= =,后来看别人的博客才知道要用到状态压缩,以这一题为例,有四种钥匙,每把钥匙的数量不是重点,如果用一个2^4的数保存即可,先将每种钥匙分别赋值为0,1,2,3,从0000到1111一共有16种状态,每种状态不会重合,例如1110就可以表示现在有3,2,1种钥匙。
#pragma comment(STACK/linker,"102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<cmath> #include<map> #include<set> #include<stack> #include<deque> using namespace std; typedef long long ll; #define for1(i,a) for(int (i)=1;(i)<=(a);(i)++) #define for0(i,a) for(int (i)=0;(i)<(a);(i)++) #define mem(i,a) memset(i,a,sizeof i) #define sf scanf #define pf printf char g[101][101]; int m,n,i,j,k,x1,y1; bool vis[101][101][110]; const int dx[]={0,0,1,-1}; const int dy[]={1,-1,0,0}; char g1[]={'b','r','y','g'};//将钥匙赋值 char g2[]={'B','R','Y','G'};//将门赋值 struct Node { int x,y,t,k; Node(){} }que[100010]; void solve() { Node tmp,p; int s,e; s=e=0; tmp.x=x1,tmp.y=y1,tmp.t=0,tmp.k=0; vis[tmp.x][tmp.y][tmp.k]=1; que[e++]=tmp; while(s<e) { tmp=que[s++]; for0(i,4) { p=tmp; p.x+=dx[i],p.y+=dy[i],p.t++; if(p.x<1||p.x>m||p.y<1||p.y>n||g[p.x][p.y]=='#') continue; if(g[p.x][p.y]=='X') { pf("Escape possible in %d steps.\n",p.t); return ; } if(g[p.x][p.y]>'A'&&g[p.x][p.y]<'Z')//如果遇到门,就用保存钥匙状态的数对其移位做按位与运算,如果不为0就表示有这种钥匙 { for(j=0;j<4;j++) if(g[p.x][p.y]==g2[j]) if(p.k&(1<<j)) if(!vis[p.x][p.y][p.k]) vis[p.x][p.y][p.k]=1,que[e++]=p; } else if(g[p.x][p.y]>'a'&&g[p.x][p.y]<'z')//如果遇到钥匙,就将当前保存钥匙状态的数更新 { for(j=0;j<4;j++) if(g[p.x][p.y]==g1[j]) { p.k=p.k|(1<<j); if(!vis[p.x][p.y][p.k]) vis[p.x][p.y][p.k]=1,que[e++]=p; } } else if(!vis[p.x][p.y][p.k]) vis[p.x][p.y][p.k]=1,que[e++]=p; } } pf("The poor student is trapped!\n"); } int main() { while(sf("%d%d",&m,&n),m+n) { mem(vis,0); for1(i,m) for1(j,n) { cin>>g[i][j]; if(g[i][j]=='*') vis[i][j][0]=1,x1=i,y1=j; } solve(); } return 0; }