• hdu1429 胜利大逃亡(续) 【BFS】+【状态压缩】


    题目链接:https://vjudge.net/contest/84620#problem/K

    题目大意:一个人从起点走到终点,问他是否能够在规定的时间走到,在走向终点的路线上,可能会有一些障碍门,他需要在路上捡到开门的对应钥匙,才能通过这扇门。如果他到达终点的时间超过了规定时间,或者他根本就走不到终点,输出-1,否则的话,输出他走的步数。

    解题思路:此题与普通的bfs类似,只不过到下一个点的时候,要加上一些判断,如果是钥匙,则将它储存起来,如果是门,则判断是否已经捡到了对应的钥匙,如果有对应钥匙,则这个门与其它 '.' 无异,如果没有对应的钥匙,则不能通过。这个功能是由状态压缩来实现的,将钥匙的对应序号转化成二进制,方便钥匙的存储和判断。另外,还有一个需要注意的就是vis数组的设置,此题只要仔细思考就会发现,设置成二维的显然不行,因为走过的路是可以重复走的,只不过你钥匙的数量要增加,比如说,你走到了一扇门那里,但是你没有钥匙,你只好向别的方向继续搜索,当你捡到对应的钥匙后,可以沿着原路返回到那扇门那里。因此,为了满足题目意思,又不需要走太多重复的路,这样的设置还是挺合理的。

    #include <cstdio>                  
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    using namespace std;
    int vis[25][25][1028];            1<<10=1024
    char map[25][25];
    int dir[4][2] = {1,0,0,1,-1,0,0,-1};
    int n, m,t;
    
    struct node
    {
        int x;
        int y;
        int key;
        int step;
    };
    
    queue<node>q;
    
    int bfs()
    {
        node s,now, next;
        int i, j,nx,ny;
        while (!q.empty())
        {
            now = q.front();
            q.pop();
            if (map[now.x][now.y] == '^')
            {
                /*now.step < t ?printf("%d
    ", now.step) : printf("-1
    "); */ //不能这样写,因为它可能走不到终点
                if (now.step < t)return now.step;
            }
            for (i = 0; i < 4; i++)
            {
                nx = now.x + dir[i][0];
                ny = now.y + dir[i][1];
                if (nx < 0 || nx >= n || ny < 0 || ny >= m || map[nx][ny] == '*')continue;
                else if ((map[nx][ny] == '.'||map[nx][ny]=='^') && !vis[nx][ny][now.key])
                {
                    vis[nx][ny][now.key] = 1;
                    next.x = nx, next.y = ny;
                    next.step = now.step + 1, next.key = now.key;
                    q.push(next);
                }
                else if (map[nx][ny] >= 'A'&&map[nx][ny] <= 'J'&&vis[nx][ny][now.key] == 0)
                {
                    int key = 1 << (map[nx][ny] - 'A');
                    if (now.key&key)
                    {
                        vis[nx][ny][now.key] = 1;
                        next.x = nx, next.y = ny;
                        next.step = now.step + 1;
                        next.key = now.key;
                        q.push(next);
                    }
                }
                else if (map[nx][ny] >= 'a'&&map[nx][ny] <= 'j' && !vis[nx][ny][now.key])
                {
                    int key = 1 << (map[nx][ny] -'a');
                    vis[nx][ny][now.key] = 1;
                    next.x = nx, next.y = ny;
                    next.step = now.step + 1;
                    next.key = now.key | key;
                    q.push(next);
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        int i, j;
        node s;
        while (scanf("%d%d%d", &n, &m, &t) != EOF)
        {
            while (!q.empty())q.pop();
            memset(vis, 0, sizeof(vis));
            for (i = 0; i < n; i++)
            {
                scanf("%s", &map[i]);
                for (j = 0; j < m; j++)
                {
                    if (map[i][j] == '@')
                    {
                        s.x = i;
                        s.y = j;
                        map[i][j] = '.';
                    }
                }
            }
            s.key = 0; s.step = 0;
            vis[s.x][s.y][s.key] = 1;
            q.push(s);
            printf("%d
    ", bfs());
        }
        return 0;
    }
    2018-03-26


    作者:is_ok
    出处:http://www.cnblogs.com/00isok/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    全局变量、函数、文件基本操作、冒泡排序
    元组,字符串,集合,文件操作
    Python使用小技巧
    pycharm
    postman和charles
    将博客搬至CSDN
    垃圾陷阱
    codevs 1139 观光公交
    1159 最大全0子矩阵
    NOI 193棋盘分割.cpp
  • 原文地址:https://www.cnblogs.com/00isok/p/8643639.html
Copyright © 2020-2023  润新知