NYOJ 迷宫寻宝(一)
2016-04-02 18:30
274 查看
迷宫寻宝(一)
时间限制: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代码:
时间限制: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; }
相关文章推荐
- XX2Vec算法汇总
- 【NOIP模拟】我的天
- PCM data flow - 7 - Frame & Period
- MySQL 5.7.11官网免安装版无法启动的问题
- magento 导入数据库时遇到的问题
- Java笔试题
- Java查找指定字符串第一次或最后一次出现的位置
- 51Nod 1007 正整数分组
- 蚂蚁金服发布基于AR技术的生活服务平台“蚂上”
- 【Qt】Qt Creator快捷键
- 对TCP/IP网络协议的深入浅出归纳
- C# textbox快捷键添加横杠
- 现在还有必要安装第三方杀毒软件吗?
- JAVA printWriter中write()和println()区别
- 代理模式
- Android开发:setAlpha()方法
- Mac下载安装Android Studio教程
- 在ubuntu上编译树莓派的kernel.img
- 剑指offer面试题之判断二叉搜索树的后序序列
- 职责链模式(Chain of Responsibility)的Java实现