zoukankan      html  css  js  c++  java
  • 迷宫寻宝(一) BFS

    迷宫寻宝(一)

    时间限制: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
    来源
    POJ月赛改编
    这个题做了挺长时间:
    注意:
    1.门可能有多个
    2.在搜索的时候用been标记这个门是不是可以到达,用num==key&&key>0表示当前有足够的钥匙可以通过
    3.读入的时候有多余空格,不要单个字符读入
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<fstream>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  22
    #define LLL 1000000000
    #define INF 1000000009
    #define eps 0.00000001
    /*
    BFS 搜索,在读入图的时候记录abcde所需要的钥匙个数
    先BFS一遍,找到所有能找到的钥匙。
    然后对于所有的门,如果第一次搜索能到达而且钥匙足够。
    把这个门加入队列再搜
    */
    struct node
    {
        int x, y;
        node() = default;
        node(int _x,int _y):x(_x),y(_y){}
    };
    node start,aim;
    vector<node> door[5];
    int key[5], num[5], n, m;//需要的钥匙个数,n行m列
    int x[4] = { 0,0,1,-1 }, y[4] = { 1,-1,0,0 };
    bool been[MAXN][MAXN];
    char g[MAXN][MAXN];
    int check()
    {
        for (int i = 0; i < 5; i++)
        {
            if (key[i]>0&&num[i] == key[i])
            {
                for (int j = 0; j < door[i].size(); j++)
                {
                    if(been[door[i][j].x][door[i][j].y])
                        return i;
                }
            }
        }
        return -1;
    }
    bool BFS(node s)
    {
        queue<node> q;
        been[s.x][s.y] = true;
        q.push(s);
        while (!q.empty())
        {
            node tmp = q.front();
            q.pop();
            //cout << tmp.x << ' ' << tmp.y << ' '<<g[tmp.x][tmp.y] << endl;
            if (tmp.x == aim.x&&tmp.y == aim.y)
                return true;
            if ((g[tmp.x][tmp.y] - 'A' >= 0 && g[tmp.x][tmp.y] - 'A'<5)&&(key[g[tmp.x][tmp.y] - 'A']==0||num[g[tmp.x][tmp.y] - 'A'] != key[g[tmp.x][tmp.y] - 'A']))
                continue;
            for (int i = 0; i < 4; i++)
            {
                int tx = tmp.x + x[i], ty = tmp.y + y[i];
                if (tx >= 0 && tx < n& ty >= 0 && ty <= m&&!been[tx][ty]
                     &&((g[tx][ty]=='.'||g[tx][ty]=='G'||g[tx][ty]-'A'>=0&&g[tx][ty]-'A'<5)||(g[tx][ty]-'a'>=0&&g[tx][ty]-'a'<5)))
                {
                    
                    if(g[tx][ty] - 'a' >= 0 && g[tx][ty] - 'a'<5)
                        num[g[tx][ty] - 'a']++;
                    been[tx][ty] = true;
                    q.push(node(tx, ty));
                }
            }
        }
        return false;
    }
    int main()
    {
        while (scanf("%d%d", &n, &m), n+m)
        {
            bool f = false;
            memset(been, false, sizeof(been));
            memset(num, 0, sizeof(num));
            memset(key, 0, sizeof(key));
            for (int i = 0; i < 5; i++)
            {
                door[i].clear();
            }
            for (int i = 0; i < n; i++)
            {
                scanf("%s", g[i]);
                for (int j = 0; j < m; j++)
                {
                    if (g[i][j] - 'A' >= 0 && g[i][j] - 'A' < 5)
                    {
                        door[g[i][j] - 'A'].push_back(node(i, j));
                    }
                    else if (g[i][j] - 'a' >= 0 && g[i][j] - 'a' < 5)
                    {
                        key[g[i][j] - 'a']++;
                    }
                    else if (g[i][j] == 'S')
                    {
                        start.x = i, start.y = j;
                    }
                    else if (g[i][j] == 'G')
                    {
                        aim.x = i, aim.y = j;
                    }
                }
            }
            if (BFS(start))
            {
                f = true;
                printf("YES
    ");
                continue;
            }
            while (1)
            {
                int k = check();
                if (k == -1) break;
                for (int j = 0; j < door[k].size(); j++)
                {
                    if (been[door[k][j].x][door[k][j].y])
                    {
                        if (BFS(door[k][j]))
                        {
                            f = true;
                            break;
                        }
                        door[k].erase(door[k].begin() + j);
                    }
                }
                if (f)
                    break;
            }
            if (!f)
                printf("NO
    ");
            else
                printf("YES
    ");
        }
        return 0;
    }
  • 相关阅读:
    银行卡号每隔四位添加一个分隔符
    clipboard.js实现文本复制
    选中|复制文本
    react---之下拉菜单默认选中的值始终不变的问题
    create-react-app支持less配置
    数对
    安置路灯
    被三整除
    牛牛找工作
    C++ std::pair
  • 原文地址:https://www.cnblogs.com/joeylee97/p/6839206.html
Copyright © 2011-2022 走看看