openjudge2.5基本算法之搜索——1159:Maze

文章讲述了Acm在特殊迷宫中的寻宝过程,需要找到所有门的钥匙才能打开通往宝藏的门。通过广度优先搜索算法判断Acm能否找到宝藏。
摘要由CSDN通过智能技术生成

题目

`1159:Maze
描述
Acm, a treasure-explorer, is exploring again. This time he is in a special maze, in which there are some doors (at most 5 doors, represented by ‘A’, ‘B’, ‘C’, ‘D’, ‘E’ respectively). In order to find the treasure, Acm may need to open doors. However, to open a door he needs to find all the door’s keys (at least one) in the maze first. For example, if there are 3 keys of Door A, to open the door he should find all the 3 keys first (that’s three 'a’s which denote the keys of ‘A’ in the maze). Now make a program to tell Acm whether he can find the treasure or not. Notice that Acm can only go up, down, left and right in the maze.
输入
The input consists of multiple test cases. The first line of each test case contains two integers M and N (1 < N, M < 20), which denote the size of the maze. The next M lines give the maze layout, with each line containing N characters. A character is one of the following: ‘X’ (a block of wall, which the explorer cannot enter), ‘.’ (an empty block), ‘S’ (the start point of Acm), ‘G’ (the position of treasure), ‘A’, ‘B’, ‘C’, ‘D’, ‘E’ (the doors), ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ (the keys of the doors). The input is terminated with two 0’s. This test case should not be processed.
输出
For each test case, in one line output “YES” if Acm can find the treasure, or “NO” otherwise.
样例输入
4 4
S.X.
a.X.
…XG

3 4
S.Xa
.aXB
b.AG
0 0
样例输出
YES
NO

翻译

题目
Acm,一个宝藏探索者,又开始探索了。这次他在一个特殊的迷宫中,迷宫中中一些门(最多5个门,分别用“a”、“B”、“C”、“D”、“E”表示)。为了找到宝藏,Acm可能需要打开门。然而,要打开一扇门,他需要首先找到迷宫中所有门的钥匙(至少一把)。例如,如果A门有3把钥匙,要打开门,他必须先找到所有3把钥匙(即3个“A”代表迷宫中A的钥匙)。现在编一个程序告诉Acm他是否能找到宝藏。注意,Acm在迷宫中只能上、下、左、右走。
输入
输入由多个测试用例组成。每个测试用例的第一行包含两个整数M和N (1 < N, M < 20),表示迷宫的大小。接下来的M行是迷宫布局,每行包含N个字符。字符是下列字符之一:‘X’(一块墙,浏览器不能进入),'。’(一个空方块),‘S’(Acm的起点),‘G’(宝藏的位置),‘A’,‘B’,‘C’,‘D’,‘E’(门),‘A’,‘B’,‘C’,‘D’,‘E’(门的钥匙)。
输入端以两个0结束。不应该处理这个测试用例。
输出
对于每个测试用例,如果Acm能找到宝藏,在一行中输出“YES”,否则输出“NO”。

理解

建图时,记清楚S出发点(队列最开始仅有元素)。遇到钥匙’a’或’b’、‘c’、‘d’、‘e’,
记住钥匙-‘a’=0或1、2、3、4对应五个门需要的钥匙数。
队列里取出队首,上下左右移动,到达那里就要用数组标记,不得重复访问。
如果是’X’墙不能放进队列,'.‘可以,
到达门’A’或’B’.‘C’.‘D’.‘E’如果需要钥匙不够就不能放进队列,
钥匙’a’或’b’、‘c’、‘d’、'e’放进队列并少各门需要钥匙数,
同时通过不需要钥匙的前面到达过(标记过)的对应门,放进队列。
门-'A’和钥匙-'a’都要转换成对应数字。

自建数据

很多时候题目附带的测试数据只体现部分题目诉求,需要深度理解情景,归纳问题。最好能自建数据,以论证规律。
在访问三把钥匙a前就能访问门A。所以每次找到钥匙都可以尝试去开前面能访问的门

代码

#include <bits/stdc++.h>
using namespace std;
struct node{
int x,y;//行列
};
int m,n,
d[4][2]={{-1,0},{0,-1},{1,0},{0,1}},//向上下左右四个方向移动
dk[5];//五个门分别的钥匙数量
char maze[25][25];//迷宫每个坐标字符
bool k[25][25];//表示来过了
node door[5];//五个门的位置
queue q;//广搜队列,先进先出
void view(){
cout<<“线路”<<endl;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)cout<<maze[i][j]<<“:”<<k[i][j]<<“\t”;
cout<<endl;
}
cout<<“钥匙,”;
for(int i=0;i<5;i++)cout<<char(i+‘a’)<<“:”<<dk[i]<<“\t”;cout<<endl;
}
int main(){
//freopen(“data.cpp”,“r”,stdin);
while(cin>>m>>n&&m&&n){
//多组数据要清空
memset(dk,0,sizeof(dk));//钥匙数量清空
memset(k,0,sizeof(k));//钥匙数量清空
while(!q.empty())q.pop();//清空队列
for(int i=0;i<5;i++)door[i]=node{0,0}; //清空门
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>maze[i][j];//输入每个格子
if(maze[i][j]>=‘A’&&maze[i][j]<=‘E’)//如果是门
door[maze[i][j]-‘A’]=node{i,j};//记住门的位置
else if(maze[i][j]>=‘a’&&maze[i][j]<=‘e’)//如果是钥匙
dk[maze[i][j]-‘a’]++;//增加钥匙数量
else if(maze[i][j]= =‘S’){//迷宫入口
q.push(node{i,j}); k[i][j]=1;
}
}
}
//view();//显示迷宫
bool key=0;
while(!q.empty()){//队列非空就循环
int x=q.front().x,y=q.front().y;q.pop();//取出队列首元素,并去除首元素
if(maze[x][y]==‘G’){key=1;break;}//找到财宝
for(int i=0;i<4;i++){//去往上下左右四个方向
int x2=x+d[i][0],y2=y+d[i][1];//新坐标
if(maze[x2][y2]!=‘X’&&!k[x2][y2]&&x2>=1&&x2<=m&&y2>=1&&y2<=n){
//只要不是墙,在迷宫内,并且没来过
k[x2][y2]=1;//就要标记
if(maze[x2][y2]>=‘A’&&maze[x2][y2]<=‘E’&&dk[maze[x2][y2]-‘A’])continue;
//钥匙没凑齐,门就不能过,不放在队列里出,只标记来过了
else if(maze[x2][y2]>=‘a’&&maze[x2][y2]<=‘e’){
dk[maze[x2][y2]-‘a’]–;//标记多了把钥匙
int dx=maze[x2][y2]-‘a’;//用0、1、2、3、4表示ABCDE门,也表示abcde钥匙
if(k[door[dx].x][door[dx].y]&&!dk[maze[door[dx].x][door[dx].y]-‘A’])q.push(door[dx]);
//前面到过该门,现钥匙齐了,可以进门,放进队列里
}
q.push(node{x2,y2});//宽搜,放进队列
}
}
//view();
}
if(key)cout<<“YES”<<endl;
else cout<<“NO”<<endl;
}
return 0;
}

错误经验

多组测试数据,必须要清零。

总结

提高英语阅读理解能力,做题要静心、耐心,不懂就慢慢理解。要根据提意创建数据。

  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值