迷宫寻宝(一)
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
一个叫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

这一题写了一天。。。遍历图其实有两种方法,一种是bfs(宽度优先搜索),另一种dfs(深度优先搜索),像这种图的遍历一般建议用bfs,两种方法具体实现没法跟你讲,自己查资料或浏览以下AC代码。本题的思路是这样的,先从‘S’出发调用bfs,实时判断是否到达‘G’,找到了最好,如果未找到怎么办呢?就是得判断有没有出现过无法通过的门。所以这就需要用数组记录下之前无法通过的门,然后再遍历这些门,如果遇到一些门找到钥匙则以该门为起点继续调用bfs,如此往复。所以这是个好题。代码以注释

AC代码:

/*以下代码在下原创,如有不足多多指正*/# include <stdio.h>
# include <string.h>
# include <ctype.h>
# include <stdlib.h>
# include <queue>
using namespace std;  queue<int> q;int m, n;
int vis[50][50];
int a[200];
int des[200];
char g[50][50];
//这个结构体的作用就是用来记录当时遇到门时,没足够钥匙的门
struct node{int r;int c;int flage;//先前遇到打不开的门,还未处理时记为1 ,处理后记为零
};int x[4]={0, 0, 1, -1};
int y[4]={1, -1, 0, 0};
int cnt, Find, Flage;
struct node s[410];
//init()函数进行初始化,就是在外围加一圈'X'
//这样做感觉便于操作,不用判断边界
void init(){for(int i=0; i<=n+1; i++){g[0][i]='X';}for(int i=1; i<=m; i++){g[i][0]='X';g[i][n+1]='X';}for(int i=0; i<=n+1; i++){g[m+1][i]='X';}
}
void bfs(){//宽度优先搜索函数 int r, c, num;while(!q.empty()){num=q.front(); q.pop();r=num/n+1;c=num%n;if(c==0){r--;c=n;}for(int i=0; i<=3; i++){if(g[r+x[i]][c+y[i]]=='G'){Find=1;//找到'G' return;}if(!vis[r+x[i]][c+y[i]]){if(isalpha(g[r+x[i]][c+y[i]])){//g[i][j]为字母 if(g[r+x[i]][c+y[i]]>='a'){//找到一把钥匙 a[g[r+x[i]][c+y[i]]]++;//总数加一 g[r+x[i]][c+y[i]]='.';//化为'.' ,即可行的路 vis[r+x[i]][c+y[i]]=1;q.push((r+x[i]-1)*n+c+y[i]);}else if(g[r+x[i]][c+y[i]]<='E'){//遇到门 if(a[g[r+x[i]][c+y[i]]+32]==des[g[r+x[i]][c+y[i]]+32]){//如果钥匙数已经够可以开门 g[r+x[i]][c+y[i]]='.';vis[r+x[i]][c+y[i]]=1;q.push((r+x[i]-1)*n+c+y[i]);}else{//如果钥匙数还不够,记录一下门的位置 s[cnt].r=r+x[i];s[cnt].c=c+y[i];s[cnt].flage=1;cnt++;}}}else{vis[r+x[i]][c+y[i]]=1;q.push((r+x[i]-1)*n+c+y[i]);}}}}return;
}
int main(){int i, j, k, b_r, b_c, temp1, temp2, no;while(scanf("%d%d", &m, &n)){getchar();if(m==0&&n==0){break;}for(i=1; i<=m; i++){scanf("%s", g[i]+1);}init();while(!q.empty()){//队列初始化清空 q.pop();}memset(vis, 0, sizeof(vis));memset(a, 0, sizeof(a));memset(des, 0, sizeof(des));cnt=0;Find=0;Flage=1;for(i=1; i<=m; i++){for(j=1; j<=n; j++){if(g[i][j]=='S'){b_r=i;b_c=j;}if(isalpha(g[i][j])&&g[i][j]>='a'){des[g[i][j]]++;//记录门对应的钥匙总数 }}}g[b_r][b_c]='.';vis[b_r][b_c]=1;no=(b_r-1)*n+b_c;q.push(no);bfs();//从'S'点开始调用bfs while(!Find&&Flage){//Find!=1时表示还没找到'G';// Flage==1时表示之前有一个无法通过的门现在找到钥匙//则以这个门为起点再次调用bfs Flage=0;for(i=0; i<=cnt-1; i++){temp1=s[i].r;temp2=s[i].c;if(g[temp1][temp2]>='A'&&g[temp1][temp2]<='E'&&s[i].flage&&a[g[temp1][temp2]+32]==des[g[temp1][temp2]+32]){s[i].flage=0;Flage=1;break;}}if(Flage){memset(vis, 0, sizeof(vis));g[temp1][temp2]='.';vis[temp1][temp2]=1;while(!q.empty()){q.pop();}q.push((temp1-1)*n+temp2);bfs();}}if(Find){//Find==1表示找到 printf("YES\n");}else{printf("NO\n");}}return 0;
}

NYOJ 迷宫寻宝(一)相关推荐

  1. NYOJ迷宫寻宝(一)

    不知道为什么思路都是一样的偶写滴就超时= = 我写的 #include<stdio.h> #include<string.h>int m,n,x1,y1,flag,key[5] ...

  2. 迷宫寻宝(自编简单版)

    nyoj - 迷宫寻宝(1) 我觉得有点难...我将其改简单一些. 题目描述:与原题基本差不多,但开门条件改一下,每个门只需要一把钥匙即可打开,一把钥匙可以开所有对应的门. 这样就简单很多啦...其实 ...

  3. NYOJ 82:迷宫寻宝(一)(BFS)

    迷宫寻宝(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号 ...

  4. nyoj 81 迷宫寻宝

    迷宫寻宝(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编 ...

  5. 《搜索》— NYOJ 82 迷宫寻宝(一)

    迷宫寻宝(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号 ...

  6. nyoj82(迷宫寻宝)

    nyoj82(迷宫寻宝) 迷宫寻宝(一) 时间限制: 1000 ms  |  内存限制: 65535 KB 难度: 4 描述 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个 ...

  7. 迷宫寻宝(一) 82

    /*迷宫寻宝(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编 ...

  8. 迷宫寻宝(宽度搜索)(C++)

    迷宫寻宝 题目 一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,不限时间和步数,当然也没有陷阱,请你判断他能不能顺利的得到宝藏. 输入 多组输入 每组测试数据的第一行包含了两个整数M ...

  9. Qt利用深度优先搜索实现迷宫寻宝

    先看效果: 利用QT搭建迷宫界面 利用单选框来构造迷宫,设置障碍物和宝藏的位置 利用深度优先搜索实现迷宫寻宝,并且在寻找的过程中避开障碍物. 搜索算法在线程中进行 定义方格的属性 enum Signa ...

最新文章

  1. DPDK 大页内存原理(二十一)
  2. 修复Chrome上的ERR_TOO_MANY_REDIRECTS错误?
  3. 短信验证码、图形验证码、邮件验证的自动化测试
  4. 技本功丨知否知否,Redux源码竟如此意味深长(下集)
  5. mysql 更新日的数据类型_[每日更新-MySQL基础]5.常用的数据类型-整数和字符串
  6. 苏杰专访:产品创新好方向=几十年不变的需求+硬科技赋能
  7. 关于数据传输格式的序列化和反序列化
  8. 采用什么样的辅助工具能够有效地帮助孩子提高英语及数学的成绩?
  9. 情人节快乐(转)十五首最美爱情古诗词,伴你过一个温馨浪漫的情人节
  10. 计算机键盘都起什么作用,电脑键盘各个按键功能 电脑键盘各个按键有什么功能...
  11. vue 中的el表达式_解释el页面数据表达式
  12. 网易租赁服务器怎么添加组件,《我的世界》租赁服添加MOD教程 租赁服怎么添加小精灵MOD?...
  13. 一度智信电商:店铺转化率太低?
  14. 重装Win10系统有教程吗?如何在线一键重装Win10系统?
  15. 大数据实战 --- 淘宝用户行为数据分析
  16. doraemon的python 协程
  17. 纪念周恩来诞辰124周年
  18. 软件定义网路核心原理与应用实践(二)SDN接口协议
  19. 基于JSP的网上手机销售系统
  20. 如何正确估计期权的Greeks?

热门文章

  1. win10计算机临时网络设置,win10系统创建无线临时网络连接的操作步骤
  2. Com插件开发-CDR插件-自动化接口-IDispatch接口-原理解析
  3. 笨办法学python3 学习笔记 习题42 对象、类及从属关系
  4. 怎么修改照片dpi值?怎么提高照片分辨率dpi?
  5. 评测:北京歌华数字电视升级后的使用体验
  6. tableau高级绘图(十三)-tableau绘制K线图
  7. JSP使用EL表达式
  8. php输出函数是什么,PHP输出函数
  9. 分子对接教程 | (2) 选择合适的蛋白受体
  10. 青云QingCloud推出AppCenter 2.0 对话合作伙伴分享上云价值