您的位置:首页 > 其它

【BFS】迷宫寻宝(一)(nyoj-82)

2013-07-12 15:59 267 查看
题目链接点击打开链接

BFS题,看下NYOJ的讨论区,感觉数据挺变态。不过居然一遍就AC了......

好吧,个人觉得这题比较恼人的地方就是,一扇门需要集齐地图中的所有钥匙才能够打开。

这一点我刚写的时候没有仔细看(还以为是一把钥匙一扇门),结果对题目给的第二组测试数据纠结了很久.....

我的思路是:开一个key数组,在录入地图的时候,每逢a-e的钥匙出现,就计数+1;
在BFS过程中,每次遇到了一把钥匙,相应的计数就减去1,这样,当一把钥匙计数为0时,就代表着所有的钥匙都已经收集完全,可以打开对应的们了。
然而,有的钥匙由于被某一扇门阻隔,当前状态下无法收集,我们需要将别的门打开之后才能收集到。因此,判断当前状态下无法开启的们,未必在整个过程中都无法开启。因此,我们不能简单的在否定“入队”操作之后置之不理。
我的方法是将不能打开的们重新插入队尾。当然,为了防止死循环,必须先判断队列是否为空,如果队列为空,则表示该们无论如何都无法开启。
具体实现如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
char map[35][35];
bool visit[35][35];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int key[5]={0};
int n,m;
struct node
{
int i,j;
};
bool in_limit(node & in)
{
if(in.i<1||in.j<1||in.i>n||in.j>m||visit[in.i][in.j])
return false;
char temp=map[in.i][in.j];
if(temp=='X')
return false;
if(temp<='e'&&temp>='a')
key[temp-'a']--;
return true;
}
bool BFS(int si,int sj)
{
node in,out;
in.i=si;
in.j=sj;
queue<node>que;
que.push(in);
visit[in.i][in.j]=1;
while(!que.empty())
{
out=que.front();
que.pop();
int tep=map[out.i][out.j];
if(tep=='G')
return true;
if(tep<='E'&&tep>='A')
{
if(key[tep-'A']==0)
{
map[out.i][out.j]='.';
}
else
{
if(que.empty())
return false;
else
{
que.push(out);
continue;
}
}
}
for(int i=0;i<4;i++)
{
in.i=out.i+dir[i][0];
in.j=out.j+dir[i][1];
if(!in_limit(in))
continue;
visit[in.i][in.j]=1;
que.push(in);
}
}
return false;
}

int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&(m||n))
{
getchar();
memset(key,0,sizeof(key));
int si,sj;
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='S')
{
si=i;
sj=j;
}
if(map[i][j]<='e'&&map[i][j]>='a')
key[map[i][j]-'a']++;
}
if(BFS(si,sj))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: