bfs专题之HUD 1429 胜利大逃亡(续)

本文解析了HDU 1429题目中的BFS算法实现细节,重点介绍了如何利用位运算记录钥匙状态,并通过三维数组进行状态压缩来避免重复访问同一状态。文中提供了一个完整的C语言实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.hdu.edu.cn/showproblem.php?pid=1429

第一次做 感觉有点困难 毕竟接触 BFS不久

两点值得学习

1,记录10把钥匙的状态 即vis[][][1024]的 作用   1024  (2^10)中状态  。。。状态   学长 屡次强调 且 屡次解释 的一个 东西

每种状态只能走一个点一次  这是和 最简单迷宫的 区别  。。

2,位运算  >>  <<  &  |       这与上面的1024相对应 ,作为新手这个的确不大熟悉 。。。。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct node
{
    int x,y;
    int step,key;
}dui[5000000];
int s_x,s_y,e_x,e_y,t;
int n,m;
int dir[4][2]={0,1,0,-1,1,0,-1,0};
char map[25][25];
int mark[25][25][1025];
int bfs()
{
    int i,j,head,tail;
    int key;
    struct node now,next;
    head=tail=0;
    dui[tail].x=s_x;
    dui[tail].y=s_y;
    dui[tail].step=0;
    dui[tail++].key=0;
    while(head<tail)
    {
        now.x=dui[head].x;
        now.y=dui[head].y;
        now.step=dui[head].step;
        now.key=dui[head++].key;
        for(i=0;i<4;i++)
        {
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];
            next.step=now.step+1;
            next.key=now.key;
            if(next.x<0 || next.x>=n ||next.y<0 || next.y>=m) continue;
            if(map[next.x][next.y]=='*') continue;
            if(map[next.x][next.y]>='a' && map[next.x][next.y]<='j')
            {
                key=1<<(map[next.x][next.y]-'a');
                next.key=next.key|key;
            }
            else if(map[next.x][next.y]>='A' && map[next.x][next.y]<='J')
            {
                key=1<<(map[next.x][next.y]-'A');
                if( (key&next.key)==0 ) continue;
            }
           if(mark[next.x][next.y][next.key]) continue;
           mark[next.x][next.y][next.key]=1;
           if(next.x==e_x && next.y==e_y)
           {
               if(next.step<t) return next.step;
               else return -1;
           }
           dui[tail].x=next.x;
           dui[tail].y=next.y;
           dui[tail].step=next.step;
           dui[tail++].key=next.key;
        }
    }
    return -1;
}
int main()
{
    int i,j;
    while(scanf("%d%d%d",&n,&m,&t)!=EOF)
    {
        getchar();
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                scanf("%c",&map[i][j]);
                if(map[i][j]=='@')
                {
                    s_x=i; s_y=j;
                }
                else if(map[i][j]=='^')
                {
                    e_x=i; e_y=j;
                }
            }
            getchar();
        }
        memset(mark,0,sizeof(mark));
        printf("%d\n",bfs());
    }
    return 0;
}

### ACM竞赛‘胜利大逃亡’问题解决方案 #### 背景介绍 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力、建模抽象能力、灵活度[^1]。对于特定题目如“胜利大逃亡”,这类问题通常涉及路径寻找或最优解计算。 #### 问题描述 假设在一个迷宫环境中存在多个起点和终点,“胜利大逃亡”的目标是从任意一个起始位置到达至少一个安全出口的位置,并且希望找到最短逃生路线长度。此类问题可以被看作是一个图论上的广度优先搜索(BFS)或者单源最短路径(Dijkstra's Algorithm)求解实例化版本之一。 #### 方法概述 针对这个问题,采用BFS来解决会更加合适一些,因为它能够保证最先访问到的目标节点即为距离最近者;而Dijkstra虽然也可以处理带权边的情况,但对于本题而言显得有些复杂而不必要。具体实现如下: ```python from collections import deque def bfs_escape(maze, start_positions): rows = len(maze) cols = len(maze[0]) directions = [(0,-1), (-1,0), (0,+1), (+1,0)] # 左 上 右 下 queue = deque() visited = set() for pos in start_positions: if maze[pos[0]][pos[1]] != '#': # 如果不是墙,则加入队列 queue.append((pos, 0)) visited.add(pos) while queue: current_pos, steps = queue.popleft() x, y = current_pos # 判断当前位置是否为边界(出口),如果是则返回步数作为结果 if x == 0 or x == rows - 1 or y == 0 or y == cols - 1: return steps for dx, dy in directions: nx, ny = x + dx, y + dy next_pos = (nx, ny) if 0 <= nx < rows and 0 <= ny < cols \ and next_pos not in visited \ and maze[nx][ny] != '#': queue.append((next_pos, steps + 1)) visited.add(next_pos) return "IMPOSSIBLE" ``` 此段Python代码实现了基于宽度优先遍历的方法去尝试从给定的一个或多个初始坐标出发,在二维字符数组表示的地图上探索是否存在通往地图边缘的安全通道。如果找到了这样的通路,则输出最小移动次数;如果没有可行出路,则报告无法逃脱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值