搜索算法之迷宫问题

迷宫问题

Description

  给定一个n×m方格的迷宫,迷宫里有t处障碍,障碍处不可通过。给定起点坐标和终点坐标,问每个方格最多经过1次,在迷宫中移动有上下左右四种方式,保证起点上没有障碍。问:
  ① 有多少种从起点坐标到终点坐标的方案?
  ② 从起点到终点的最短路径长度是多少?输出一条长度最短的路径经过的点的坐标,若不

存在起点到终点的路径,则输出-1.

Input

第一行n、m和t,其中:n为行数,m为列数,t为障碍数。
第二行起点坐标sx、sy,终点坐标ex、ey。
接下来t行,每行为障碍的坐标。

Output

第一行从起点坐标到终点坐标的方案总数。
若存在解答,则第二行输出最短路径的长度len(起点和终点也算在步数内),以下len行,每行输出经过点的坐标(i, j);
否则无解时输出-1

Sample Input

4 5 4
0 0 3 4
0 2
1 1
2 3
3 1

Sample Output

3
8
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(3, 2)
(3, 3)
(3, 4)

analysis

  使用深搜和广搜

Source Code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 150
int map[MAX][MAX],book[MAX][MAX],path[MAX][2];  //地图和标记 
int n,m,t,sx,sy,ex,ey;              //行、列、障碍数、起点坐标、终点坐标 
int num=0;                          //方案总数 
int dir[4][2]={
    {0, 1},                         //右 
    {1, 0},                         //下 
    {0,-1},                         //左 
    {-1,0},                         //上 
};
struct Node{                        //队列 
    int x;
    int y;
    int len;
    int f;
}Queue[MAX];
int head,tail;                      //队列的头尾指针 

int go(int x, int y)
{
    if (x<0 || x>=n || y<0 || y>=m)
        return 0;
    else 
        return 1;
}
void dfs(int x, int y)
{
    int nx,ny;
    if (x==ex && y==ey)
    {
        num++;return ;
    }
    for (int k=0; k<4; k++)
    {
        nx=x+dir[k][0]; ny=y+dir[k][1];
        if (go(nx, ny)==1 && map[nx][ny]==0 &&book[nx][ny]==0)
        {
            book[nx][ny]=1;
            dfs(nx, ny);
            book[nx][ny]=0;
        }
    }
    return ;
}
void bfs(int x, int y)
{
    int nx,ny;
    for (int k=0; k<4; k++)
    {
        nx=x+dir[k][0]; ny=y+dir[k][1];
        if (go(nx, ny)==1 && map[nx][ny]==0 &&book[nx][ny]==0)
        {
            Queue[tail].x=nx;
            Queue[tail].y=ny;
            Queue[tail].len=Queue[head].len+1;
            Queue[tail].f=head;
            tail++;
            book[nx][ny]=1;
            if (nx==ex && ny==ey)
                return ;
        }
    }
    head++;
    bfs(Queue[head].x, Queue[head].y);

}
int main()
{
    int tx,ty,t;                    //用于临时存储坐标 
    int i,j;
    int len;
    memset(book, 0, sizeof(book));
    memset(path, 0, sizeof(path));
    //freopen("test.in","r",stdin);
    scanf("%d %d %d", &n, &m, &t);
    scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
    for (i=0; i<t; i++)
    {
        scanf("%d %d", &tx, &ty);
        map[tx][ty]=1;  
    }
    book[sx][sy]=1;
    dfs(sx, sy);

    memset(book, 0, sizeof(book));      //初始化标记和头尾指针 
    head=tail=0;
    Queue[tail].x=sx;
    Queue[tail].y=sy;
    Queue[tail].len=1;
    Queue[tail].f=0;
    tail++;
    printf("%d\n", num);
    bfs(sx, sy);
    len=Queue[--tail].len;
    printf("%d\n", len);
    i=tail;
    j=len-1;
    path[j][0]=ex;path[j][1]=ey;
    j--;
    while (i>1)
    {
        t=Queue[tail].f;
        path[j][0]=Queue[t].x;
        path[j][1]=Queue[t].y;
        tail=t;
        i--;j--;
    }
    for (j=0; j<len; j++)
        printf("(%d,%d)\n", path[j][0], path[j][1]);
    //fclose(stdin);
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
广度优先搜索算法是一种非常常见的路径搜索算法。它通常用于求解迷宫问题,在Python中也可以很容易地实现。 实现广度优先搜索算法需要使用一个队列来存储待搜索的节点,并维护一个visited集合,用来存储已经遍历过的节点。从起始节点开始,不断将相邻的节点加入队列中,并标记为已访问。当队列为空时,表明搜索已经完成。 在求解迷宫问题时,我们可以通过二维数组来表示迷宫的结构。0表示通路,1表示墙壁。我们还需要定义起始点和终点。使用广度优先搜索算法,我们可以找到从起点到终点的最短路径,并标记所有经过的点。 具体实现步骤如下: 1. 定义迷宫结构和起点终点坐标。 2. 定义队列和visited集合。 3. 将起点加入队列,并标记为visited。 4. 不断从队列中弹出节点,扩展它的相邻节点,如果未被visited,则将其加入队列并标记为visited。 5. 如果发现终点已经被访问,则搜索结束,并从终点逆推路径,标记所有经过的点。 一个简单的Python实现可能如下所示: ```python def bfs_maze(maze, start, end): queue = [start] visited = set([start]) parents = {start: None} while queue: curr = queue.pop(0) if curr == end: break for move in ((0, 1), (0, -1), (1, 0), (-1, 0)): next_pos = (curr[0] + move[0], curr[1] + move[1]) if next_pos[0] < 0 or next_pos[0] >= len(maze) or \ next_pos[1] < 0 or next_pos[1] >= len(maze[0]): continue if maze[next_pos[0]][next_pos[1]] == 1 or next_pos in visited: continue parents[next_pos] = curr queue.append(next_pos) visited.add(next_pos) if end not in parents: return None path = [] curr = end while curr: path.append(curr) curr = parents[curr] return path[::-1] ``` 以上实现中,parents字典是用来存储每个节点的父节点,方便后面逆推路径。“[::-1]”语法是Python中用于反转列表的语法。 在实际使用过程中,需要根据具体问题进行调整和优化,比如可以加入启发式算法来加快搜索速度,或者优化搜索顺序来减少搜索次数等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值