题目链接点击打开链接
迷宫寻宝(一)
时间限制:
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
-
输入可能会有多组测试数据(不超过10组)。
思路:dfs+贪心?,从源点开始dfs,尽可能的走过更多的地方,拿到更多的钥匙,每一次dfs将拿到钥匙的点或已经打开的门都重置为空地,也就是将他们变为'.' ,利用一个标记变量来记录每一次是否有新的进展,如果没有那么永远都不能拿到宝藏,如果有就继续dfs.
#include <bits/stdc++.h>
using namespace std;
char ma[25][25];
int n, m, gx, gy, mark;
int cnt[5];//a,b,c,d,e数量
int fin[5];
bool vis[25][25];
bool val(int x, int y){
if( x<1||x>n||y<1||y>m||ma[x][y]=='X'||!vis[x][y] )return false;
return true;
}
void dfs(int curx, int cury){
if( mark==1 )return;
vis[curx][cury] = false;
char t = ma[curx][cury];
if( t>='a'&&t<='e' ){
fin[t-'a']++;
ma[curx][cury] = '.';
if( mark!=1 ) mark = 0;
}
if( t>='A'&&t<='E' ){
if( fin[t-'A']==cnt[t-'A'] ){
ma[curx][cury] = '.';
if( mark!=1 ) mark = 0;
}else return;
}
if( t=='G' ){
mark = 1;
return;
}
if( val(curx-1,cury) ) dfs(curx-1,cury);
if( val(curx+1,cury) ) dfs(curx+1,cury);
if( val(curx,cury-1) ) dfs(curx,cury-1);
if( val(curx,cury+1) ) dfs(curx,cury+1);
}
void pt(){
printf("ma:\n");
for( int i = 1; i <= n; i++ ){
for( int j = 1; j <= m; j++ ){
printf("%c",ma[i][j]);
}
printf("\n");
}
printf("vis:\n");
for( int i = 1; i <= n; i++ ){
for( int j = 1; j <= m; j++ ){
printf("%d ",vis[i][j]);
}
printf("\n");
}
}
int main(){
int x, y;
while( scanf("%d%d",&n,&m)&&n+m ){
memset( cnt, 0, sizeof(cnt) );
memset( fin, 0, sizeof(fin) );
memset( vis, true, sizeof(vis) );
for( int i = 1; i <=n; i++ ){
getchar();
for( int j = 1; j <=m; j++ ){
scanf("%c",&ma[i][j]);
if( ma[i][j]>='a'&&ma[i][j]<='e' ){
cnt[ma[i][j]-'a']++;
}else if( ma[i][j]=='G' ){
gx = i;gy = j;
}else if( ma[i][j]=='S' ){
x = i;y = j;
}
}
}
while( true ){
mark = -1; //-1为初始状态,如果没变化
memset( vis, true, sizeof(vis) );
dfs(x,y);
// pt();
if( mark==-1 ){
printf("NO\n");
break;
}else if( mark==1 ){
printf("YES\n");
break;
}
}
}
return 0;
}