- 描述
-
一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了找到宝藏,ACM必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,ACM就必须找全三把钥匙才能打开A门。现在请你编写一个程序来告诉ACM,他能不能顺利的得到宝藏。
- 输入
- 输入可能会有多组测试数据(不超过10组)。
每组测试数据的第一行包含了两个整数M,N(1<N,M<20),分别代表了迷宫的行和列。接下来的M每行有N个字符,描述了迷宫的布局。其中每个字符的含义如下:
.表示可以走的路
S:表示ACM的出发点
G表示宝藏的位置
X表示这里有墙,ACM无法进入或者穿过。
A,B,C,D,E表示这里是门,a,b,c,d,e表示对应大写字母的门上的钥匙。
注意ACM只能在迷宫里向上下左右四个方向移动。
最后,输入0 0表示输入结束。 输出 - 每行输出一个YES表示ACM能找到宝藏,输出NO表示ACM找不到宝藏。 样例输入
-
4 4 S.X. a.X. ..XG .... 3 4 S.Xa .aXB b.AG 0 0
样例输出 -
YES NO
- 输入可能会有多组测试数据(不超过10组)。
这道题比较特殊的就是对门的处理,就是当前遇到门的时候有三种情况:
1.整张地图上都没有钥匙了。
2.已经找到该门对应的钥匙了。
3.可以找到该门对应的钥匙,但是当前的状态无法到达。
所以,需要将门的信息保存起来,等找到一个门所有的钥匙时,再把没有打开的门重新加入队列即可
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class doorposition
{
int x,y;
}
class node
{
int x,y;
public node(int x,int y) {
this.x=x;
this.y=y;
}
}
public class Main {
static doorposition doorpositions[];
static int keynumber[],startx,starty,endx,endy,line,row;
static char map[][];
static int directions[][]={{-1,0},{1,0},{0,-1},{0,1}};
public static boolean overmap(int x,int y)
{
if(x<0||x>=line||y<0||y>=row)return true;
else return false;
}
public static boolean finaljudge()
{
for(int i=0;i<5;i++)
if(keynumber[i]!=0)return false;
return true;
}
public static String bfs()
{
Queue<node>queue=new LinkedList<node>();
node first=new node(startx, starty);
queue.add(first);
while(!queue.isEmpty())
{
first=queue.remove();
//这里的finaljudge()判断条件容易忽略
if(first.x==endx&&first.y==endy&&finaljudge())
return "YES";
//如果遇到的是钥匙,则总的钥匙数减1,当钥匙数为0时,将该钥匙对应的门所在的位置设置成不可访问的状态(‘X’)
if(map[first.x][first.y]>='a'&&map[first.x][first.y]<='e'&&keynumber[map[first.x][first.y]-'a']>0)
{
keynumber[map[first.x][first.y]-'a']--;
if(keynumber[map[first.x][first.y]-'a']==0)
{
node doors=new node(doorpositions[map[first.x][first.y]-'a'].x,doorpositions[map[first.x][first.y]-'a'].y);
if(map[doors.x][doors.y]=='X')
queue.add(doors);
}
}
//当遇到门时,判断当前门对应的钥匙数,如果钥匙大于0,就说明到该门时,钥匙没有收集全,将门设置为不可访问状态
if(map[first.x][first.y]>='A'&&map[first.x][first.y]<='E')
{
if(keynumber[map[first.x][first.y]-'A']>0)
{
map[first.x][first.y]='X';
continue;
}
}
//不是钥匙和门的情况,设置为不可访问状态
map[first.x][first.y]='X';
//四个方向进行搜索
for(int i=0;i<4;i++)
{
node next=new node(first.x+directions[i][0], first.y+directions[i][1]);
if(overmap(next.x,next.y)||map[next.x][next.y]=='X')continue;
queue.add(next);
}
}
return "NO";
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
while(scanner.hasNext())
{
int i,j,k;
line=scanner.nextInt();
row=scanner.nextInt();
if(line==0&&row==0)break;
String strings[]=new String[line+4];
map=new char[line+4][row+4];
doorpositions=new doorposition[5];
keynumber=new int[5];
for(i=0;i<5;i++)
{
doorpositions[i]=new doorposition();
keynumber[i]=0;
}
for(j=0;j<line;j++)
{
strings[j]=scanner.next();
for(k=0;k<row;k++)
{
map[j][k]=strings[j].charAt(k);
if(map[j][k]=='S')
{
startx=j;
starty=k;
}
if(map[j][k]=='G')
{
endx=j;
endy=k;
}
//记录钥匙数
if(map[j][k]>='a'&&map[j][k]<='e')
{
keynumber[map[j][k]-'a']++;
}
//记录门的位置
if(map[j][k]>='A'&&map[j][k]<='E')
{
doorpositions[map[j][k]-'A'].x=j;
doorpositions[map[j][k]-'A'].y=k;
}
}
}
System.out.println(bfs());
}
}
}