【POJ2157】Maze

题目链接:http://poj.org/problem?id=2157
题解:
BFS爆搜
建一个bool1数组表示一个门是否走过,一个bool2数组表示任意一个点是否走过
每次走到一个钥匙,该钥匙数+1,如果这个钥匙对应的门曾经到过,而且钥匙数够了,把门放进队列里,没有到过就个普通的点一样处理
如果走到一个门,如果钥匙数等于零,那么把这个门加进队列里,如果不为零,标记为到过这个门

感觉思路没问题,POJ的discuss里的数据也都过了,可就是A不了,怒改4h水过…
这种爆搜题真是无话可说…….

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

int n,m;
int vis[101][101],vis_door[101][101];
char map[101][101];

int x [ 5 ] = { 1,-1, 0, 0 } ;
int y [ 5 ] = { 0, 0, 1,-1 } ;

struct node
{
    int x,y;
};
struct key
{
    int tot,cnt;
}k[101];

int main()
{
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        bool flag=0,a;
        memset(k,0,sizeof(k));
        memset(vis,0,sizeof(vis));
        memset(vis_door,0,sizeof(vis_door));
        for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
        queue<node> q;
        node st,t,p;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(map[i][j]=='S') st.x=i,st.y=j;
                else if(map[i][j]=='X') vis[i][j]=1;
                else if(map[i][j]>='a'&&map[i][j]<='e') k[map[i][j]-'a'].tot++;
        q.push(st);
        while(!q.empty())
        {
            p=q.front();
            q.pop();
            for(int i=0;i<=3;i++)
            {
                int nx=p.x+x[i];
                int ny=p.y+y[i];
                if(nx>=1&&nx<=n&&ny>=1&&ny<=m)
                    if(!vis[nx][ny])
                    {
                        if(map[nx][ny]>='a'&&map[nx][ny]<='e')
                        {
                            if(++k[map[nx][ny]-'a'].cnt==k[map[nx][ny]-'a'].tot&&k[map[nx][ny]-'a'].cnt>=1)
                            {
                                for(int ii=1;ii<=n;ii++)
                                    for(int jj=1;jj<=m;jj++)
                                    if(map[ii][jj]==map[nx][ny]+'A'-'a')
                                    {
                                        node hh;
                                        hh.x=ii;
                                        hh.y=jj;
                                        if(vis_door[ii][jj])
                                        {
                                            q.push(hh);
                                            vis[ii][jj]=1;  
                                        }
                                    }
                            }
                            t.x=nx;
                            t.y=ny;
                            q.push(t);
                            vis[nx][ny]=1;
                        }
                        else if(map[nx][ny]=='G')
                        {
                            flag=1;
                            break;
                        }
                        else if(map[nx][ny]>='A'&&map[nx][ny]<='E')
                        {
                            if(k[map[nx][ny]-'A'].tot==k[map[nx][ny]-'A'].cnt&&k[map[nx][ny]-'A'].cnt>=1)
                            {
                                t.x=nx;
                                t.y=ny;
                                q.push(t);
                                vis[nx][ny]=1;
                            }
                            else vis_door[nx][ny]=1;
                        }
                        else if(map[nx][ny]=='.')
                        {
                            t.x=nx;
                            t.y=ny;
                            q.push(t);
                            vis[nx][ny]=1;
                        }
                    }
            }
        }
        if(flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值