迷宫问题(回溯思想)

题目链接:https://www.luogu.org/problem/P1605

题目背景:

给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

输入格式:
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。

输出格式:
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。

输入输出样例
输入 #1

2 2 1
1 1 2 2
1 2

输出 #1

1

说明/提示
【数据规模】

1≤N,M≤5


分析:此题采用回溯的思想

1. 回溯算法概念:

        回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

        回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

        许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

2. 回溯法的基本思想

        在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。

        若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。

3. 回溯法递归框架

回溯法是对解空间的深度优先搜索,在一般情况下使用递归函数来实现回溯法比较简单,其中i为搜索的深度,框架如下:

1: int a[n];
2: try(int i)
3: {
4:     if(i>n)
5:         输出结果;
6:     else
7:     {
8:         for(j = 下界; j <= 上界; j=j+1) // 枚举i所有可能的路径
9:         {
10:             if(fun(j)) // 满足限界函数和约束条件
11:             {
12:                 a[i] = j;
13:                 ... // 其他操作
14:                 try(i+1);
15:                 回溯前的清理工作(如a[i]置空值等);
16:             }
17:         }
18:     }
19: }

c++代码实现:

#include <iostream>
using namespace std;
int pic[6][6];
int dx[4] = {0, 0, -1, 1};
int dy[4]= {-1, 1, 0, 0};
int ans = 0; //计算总的路径数
int N,M,T;
int SX, SY;
int FX, FY;
int temp[6][6];
void dfs(int x,int y)
{
    if(x==FX && y == FY)
    {
        ans++;
        return;
    }
    else
    {
        for(int i=0;i<4;i++)
        {
            if(temp[x+dx[i]][y+dy[i]] == 0 && pic[x+dx[i]][y+dy[i]]==1)
            {
                temp[x][y] = 1;
                dfs(x+dx[i], y+dy[i]);
                temp[x][y] = 0;
            }
        }
    }

}
int main()
{
    cin>>N>>M>>T;
    for(int i=1;i<=N;i++)
    {
        for (int j = 1; j <= M; j++)
        {
            pic[i][j] = 1;
        }
    }
    cin>>SX>>SY;
    cin>>FX>>FY;
    for(int i=0;i<T;i++)
    {
        int t1,t2;
        cin>>t1>>t2;
        pic[t1][t2] = 0;
    }
    dfs(SX, SY);
    cout<<ans<<endl;
    return 0;
}

python3代码实现:

# dx = [0, 1, 0, -1]
# dy = [1, 0, -1, 0]
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
INIT_ROW = 100
INIT_COL = 100

def walk(x, y):
    global count
    if x == EX and y == EY:
        count += 1
        return
    else:
        for i in range(4):

            if temp[x + dx[i]][y + dy[i]] == 0 and pic[x + dx[i]][y + dy[i]] == 1:
                temp[x][y] = 1
                walk(x + dx[i], y + dy[i])
                temp[x][y] = 0


if __name__ == '__main__':

    s1 = list(map(int, input().split(' ')))
    N, M, T = s1[0], s1[1], s1[2]

    s2 = list(map(int, input().split(' ')))
    SX, SY, EX, EY = s2[0], s2[1], s2[2], s2[3]

    pic = []
    temp = []
    for i in range(INIT_ROW):
        pic.append([0 for i in range(INIT_ROW)])
        temp.append([0 for i in range(INIT_COL)])
    for i in range(1, N+1):
        for j in range(1, M+1):
            pic[i][j] = 1
    for k in range(T):
        row = list(map(int, input().split(' ')))
        pic[row[0]][row[1]] = 0
    print(pic)
    print(temp)
    count = 0
    walk(SX, SY)
    print(count)

参考链接:https://www.bilibili.com/video/av36473519/?p=2

发布了398 篇原创文章 · 获赞 182 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/yexudengzhidao/article/details/99581443