hdu 1429

本文介绍了一种使用广度优先搜索(BFS)解决迷宫寻路问题的方法,并通过引入钥匙状态标记来避免重复路径,确保算法效率。文中详细解释了如何利用二进制位操作来表示和更新钥匙状态,以及如何实现这一算法的具体代码。

一道bfs,主要是难在如何判断是否走的多余。这个时候vis数组需要特殊处理,加个钥匙的状态。如果带着不变的钥匙走了两次,我们就可以以判断方案不行。那么如何判断钥匙的状态呢。一共有10把钥匙,这个时候可以使用2进制。比如,0000000001就代表有第一把钥匙。而1<<10 也就一千多而已。用&运算和|运算很好处理。PS:我的代码vis数组得用bool型,不然mle。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 20 + 2;
char G[maxn][maxn];
bool vis[maxn][maxn][1<<10 + 5];
struct node
{
    int x, y;
    int step, key;
};
int n, m, t;
node door, beg;
int dir[][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int check(node point)
{
    if(point.x >= 0 && point.x < n && point.y >= 0 && point.y < m && point.step < t && G[point.x][point.y] != '*' && !vis[point.x][point.y][point.key]) return true;
    return false;
}
int bfs()
{
    if(beg.x == door.x && beg.y == door.y && beg.step < t) return 0;
    queue<node> q;
    q.push(beg);
    while(!q.empty())
    {
        node sq, tq;
        sq = q.front();
        q.pop();
        if(sq.x == door.x && sq.y == door.y && sq.step < t) return sq.step;
        for(int i = 0; i < 4; i++)
        {
            //printf("yes\n");
            tq = sq;
            tq.step++;
            tq.x += dir[i][0];
            tq.y += dir[i][1];
            if(check(tq))
            {
                if(G[tq.x][tq.y] >= 'A' && G[tq.x][tq.y] <= 'J')
                {
                    int t = G[tq.x][tq.y] - 'A';
                    if(tq.key & (1<<t)) {q.push(tq); vis[tq.x][tq.y][tq.key] = 1;}
                }
                else if(G[tq.x][tq.y] >= 'a' && G[tq.x][tq.y] <= 'j')
                {
                    int t = G[tq.x][tq.y] - 'a';
                    tq.key = tq.key | (1 << t);
                    q.push(tq);
                    vis[tq.x][tq.y][tq.key] = 1;
                }
                else {q.push(tq); vis[tq.x][tq.y][tq.key] = 1;}
            }
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d%d", &n, &m, &t) == 3)
    {
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                cin>>G[i][j];
                if(G[i][j] == '^')
                {
                    door.x = i;
                    door.y = j;
                    door.step = 0;
                    door.key = 0;
                }
                if(G[i][j] == '@')
                {
                    beg.x = i;
                    beg.y = j;
                    beg.key = beg.step = 0;
                }
            }
        }
        vis[beg.x][beg.y][0] = 1;
       int ans = bfs();
       printf("%d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值