迷宫寻宝(一)
时间限制:
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中每找到一个钥匙,就将其对应种类钥匙的总数减一,这也就是说当某种钥匙总数为0时,说明可以打开其对应的门,否则不能。
-
在BFS中,有四种情况处理
-
1,碰到门:看该门的钥匙有没有全部找到,若钥匙全部找到 标记位置后直接进队。反之标记该门(为了情况2的处理)。
-
2,碰到钥匙:该种类钥匙数减一,标记位置后进队。若钥匙总数为0且其对应的门有标记(1情况中 前面查询中没能打开该门),就将该门入队,去掉对该门的标记。
-
3,碰到.或者G:标记后入队。
-
4,碰到障碍或者越界或者该位置已查找过:继续下一次搜索。
-
ac代码:
-
#include <cstdio> #include <cstring> #include <queue> using namespace std; struct node { int x, y; }; struct rec//记录钥匙的数目 以及对应门的位置 和 标记该门是否在前面查询中 没有打开 { int num, x, y, exist; }key[6]; int n, m;//行 列 int sx, sy;//起点 char map[20][20]; bool vis[20][20];//标记该位置是否查询过 int move[4][2] = {0,1, 0,-1, 1,0, -1,0};//四个方向移动 void getmap() { int i, j; for(i = 0; i < 5; ++i) { key[i].num = 0;//初始化 } for(i = 0; i < n; i++) { scanf("%s", map[i]); for(j = 0; j < m; j++) { if(map[i][j] == 'S')//记录起点 { sx = i; sy = j; } else if(map[i][j] >= 'a' && map[i][j] <= 'e') { key[map[i][j] - 'a'].num++;//记录钥匙数 } else if(map[i][j] >= 'A' && map[i][j] <= 'E') { key[map[i][j] - 'A'].x = i;//记录对应门的横轴坐标 key[map[i][j] - 'A'].y = j; key[map[i][j] - 'A'].exist = 0;//初始化 所有门都没有查询 谈不上能否打开 } } } } int judge(int x, int y)//判断是否是障碍 或者 越界 或者该位置以及查询 { if(x >= 0 && x < n && y >= 0 && y < m && map[x][y] != 'X' && !vis[x][y]) return 1; else return 0; } int BFS(int x, int y) { node now, next; queue<node> q; memset(vis, false, sizeof(vis)); now.x = x, now.y = y; q.push(now); vis[now.x][now.y] = true; while(!q.empty()) { now = q.front(); q.pop(); if(map[now.x][now.y] == 'G') return 1; for(int k = 0; k < 4; k++) { next.x = now.x + move[k][0]; next.y = now.y + move[k][1]; if(judge(next.x, next.y)) { char cc = map[next.x][next.y]; if(cc >= 'a' && cc <= 'e')//钥匙 { key[cc - 'a'].num--;//找到一个 vis[next.x][next.y] = true;//已查找过 q.push(next);//进队列 if(key[cc - 'a'].num == 0 && key[cc - 'a'].exist == 1)//找到全部钥匙 但该门在以前查询中未能打开 { node pre = {key[cc - 'a'].x, key[cc - 'a'].y}; q.push(pre);//现在的话可以打开 key[cc - 'a'].exist = 0;//去掉标记 } } else if(cc >= 'A' && cc <= 'E')//门 { if(key[cc - 'A'].num == 0)//已经找到全部钥匙 且该门 没有查找过 { q.push(next);//进队列 vis[next.x][next.y] = true;//查找过 } else//没有找齐钥匙 标记该门 key[cc - 'A'].exist = 1; } else { q.push(next); vis[next.x][next.y] = true; } } } } return 0; } int main() { while(scanf("%d%d", &n, &m), n||m) { getmap(); if(BFS(sx, sy)) printf("YES\n"); else printf("NO\n"); } return 0; }
-
输入可能会有多组测试数据(不超过10组)。