nyoj-82 迷宫寻宝(一)(DFS/BFS)

描述

一个叫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

思路:这道题用DFS或BFS都能写,所以在做时需要明确自己要用哪一种方法,以便于与想法的实现。我做时不是很确定用哪种方法,然后逻辑混乱了,理了很久。该题需要注意的是门的状态:1.钥匙未收集齐时门为墙。2.该种钥匙收集齐时此类门不存在。由此就有了取钥匙与开门的先后顺序,需要多次搜索。

考虑DFS:以深度为准,那么一次搜索是绝对不可能的,第一次搜索后会留下一些未搜索的区域,但已搜索的区域钥匙已拿完,进行第二次搜索开门。(1000ms的限时考虑DFS也是有点慌...)

考虑BFS:以广度为准,同样也会出现留下未搜索区域,多次BFS判断钥匙的状态,若搜一次后钥匙增加,那么就继续搜,若钥匙数量不变且未到达终点就结束搜索。

DFS代码如下:

#include<iostream>
#include<string.h>
#include<stdio.h> 
#include<cstring>
using namespace std;
char map[25][25];
int m,n,fag;
int k[10],vis[25][25];
int f[4][2]={0,1,0,-1,1,0,-1,0};
void dfs(int x,int y)
{
	if(fag==1) return;
	if(map[x][y]=='G'&&fag==0)
	{
	    fag=1;
		return ;
	}
	for(int i=0;i<4;i++)
	{
		int x1=x+f[i][0];
		int y1=y+f[i][1];
		if(x1<m&&x1>=0&&y1>=0&&y1<n&&vis[x1][y1]==0&&map[x1][y1]!='X')
		{
			if('A'<=map[x1][y1]&&map[x1][y1]<='E'&&k[map[x1][y1]-'A']!=0)//该门钥匙还未找齐 
			continue;
			if('a'<=map[x1][y1]&&map[x1][y1]<='e')
			{
				k[map[x1][y1]-'a']--;//找到一把门钥匙 
				map[x1][y1]='.';//变为可走 
			}
			vis[x1][y1]=1;
			dfs(x1,y1);
			vis[x1][y1]=0;
		}
	}
}
int main()
{
	while(scanf("%d%d",&m,&n)&&m!=0&&n!=0)
	{
		memset(vis,0,sizeof(vis));
		memset(k,0,sizeof(k));
		fag=0;
		int x,y;
		for(int i=0;i<m;i++)
		{
			for(int j=0;j<n;j++)
			{
				cin>>map[i][j];
				if('a'<=map[i][j]&&map[i][j]<='e')
				k[map[i][j]-'a']++;//存钥匙总数 
				if(map[i][j]=='S')//初始位置 
				{    
				    x=i,y=j;
				}
			}
		}
		vis[x][y]=1;
		dfs(x,y);//第一次搜,把一次能过的门开了,收集钥匙 
		dfs(x,y);//第二次搜,开门搜 
		if(fag==1) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
}//如果数据变态,可能会需要第三次搜。。。。。。

BFS代码如下:(参考https://blog.csdn.net/x_y_q_/article/details/52105545)

#include<iostream>
#include<string.h>
#include<queue>
#include<cstdio>
#include<string.h>
using namespace std;
struct node{
    int x, y;
};
char map[25][25],c;
int n,m;
int need[25],have[25],x1,y1,x2,y2;
int f[4][2]={0,1,0,-1,1,0,-1,0};
int bfs()
{
    int vis[25][25];
    memset(vis,0,sizeof(vis));
    int fag=0;//判断手中的钥匙有没有变化
    queue<node>q;
    node q1;
    q1.x=x1,q1.y=y1;
    vis[x1][y1]=1;
    q.push(q1);
    while(!q.empty())
	{
        q1=q.front();
        if(q1.x==x2&&q1.y==y2)   return 1;//返回1说明已经找到宝藏了
        q.pop();
        for(int i=0;i<4;i++)
		{
            int x=q1.x+f[i][0];
            int y=q1.y+f[i][1];
            if((x>n||x<=0||y>m||y<=0)||(vis[x][y]==1)||(map[x][y]=='X'))   continue;
            if(map[x][y]>='a'&&map[x][y]<='e') 
		    {
			    have[map[x][y]-'a']++;
				map[x][y]='.';fag=1;
			}
            if(map[x][y]>='A'&&map[x][y]<='E'&&have[map[x][y]-'A']<need[map[x][y]-'A'])
                continue;
            node v;
            v.x=x,v.y=y;
            vis[x][y]=1;
            q.push(v);
        }
    }
    if(fag==0)   return -1;//返回-1说明手里的钥匙没有增加,这次找不到,以后也就没有找到宝藏的希望了
    else   return 0;//返回0说明手里的钥匙增加了,或许下一次bfs就能找到宝藏
}
int main()
{
    while(cin>>n>>m&&n!=0&&m!=0)
	{
        getchar();
        memset(have,0,sizeof(have));
        memset(need,0,sizeof(need));
        for(int i=1;i<=n;i++)
		{
            for(int j=1;j<=m;j++)
			{
                cin>>c;
                map[i][j]=c;
                if(c>='a'&&c<='e')   
				   need[c-'a']++;
                if(c=='S')  
				{ 
				   x1=i,y1=j;
				}
                if(c=='G')  
				{  
				   x2=i,y2=j;
				}
            }
            getchar();
        }
        while(1)
		{
            if(bfs()==1) 
		    {
			    cout<<"YES"<<endl;   
				break;
			}
            else if(bfs()==0)
            continue;
            else if(bfs()==-1)   
		    {
		        cout<<"NO"<<endl;   
				break;
		    }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pleasantly1/article/details/81135233