NYOJ 82迷宫寻宝(一)(dfs)

迷宫寻宝(一)
时间限制: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
题解:
先遍历能走的,找到能找到的钥匙(不需要回溯)
然后对每个门判断是否有并且钥匙是否都找到,然后以门的坐标为起点进行dfs即可。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define inf 0x3f3f3f3f
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define max(a,b) a>b?a:b

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-9;
const int maxn = 22;
const int maxm = 10000005;
using namespace std;

inline int read(){
    int x(0),f(1);
    char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
struct{
    bool isHave;
    int x,y;
}door[5];
int key[5];
int findKey[5];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m,flag;
int si,sj,di,dj;
char mp[21][21];
bool vis[21][21];
void dfs2();
void dfs1(int si,int sj){
    if(si>=n||si<0||sj>=m||sj<0||mp[si][sj]=='X'||vis[si][sj]){
        return;
    }
    if(si==di&&sj==dj){
        flag=1;
    }
    if(flag){
        return;
    }
    if(islower(mp[si][sj])){
        ++findKey[mp[si][sj]-'a'];
    }
    if(mp[si][sj]>='A'&&mp[si][sj]<='E'&&door[mp[si][sj]-'A'].isHave==false){
        door[mp[si][sj]-'A'].x=si;
        door[mp[si][sj]-'A'].y=sj;
        door[mp[si][sj]-'A'].isHave=true;
        return; //注意,不能走
    }
    vis[si][sj]=true;
    for(int i=0;i<4;++i){
        dfs1(si+dx[i],sj+dy[i]);
    }
    dfs2();
}
void dfs2(){
    for(int i=0;i<5;++i){
        if(findKey[i]==key[i]&&door[i].isHave){
            dfs1(door[i].x,door[i].y);
        }
    }
}
int main(){
   // fin;
    char str[22];
    while(~scanf("%d%d",&n,&m),n,m){
        flag=0;
        mes(door,false);
        mes(vis,false);
        mes(key,0);
        mes(findKey,0);
        for(int i=0;i<n;++i){
            scanf("%s",str);
            for(int j=0;j<m;++j){
                mp[i][j]=str[j];
                if(str[j]=='S'){
                    si=i,sj=j;
                }else if(str[j]=='G'){
                    di=i,dj=j;
                }else if(islower(str[j])){
                    ++key[str[j]-'a'];
                }
            }
        }
        dfs1(si,sj);
        if(flag){
            puts("YES");
        }else{
            puts("NO");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值