繁体   English   中英

我试图用下面的代码解决这个迷宫。 但是对于所有输入(例如n = 4),答案并不准确

[英]I was trying to solve this maze with the following code. But the answers aren't accurate for all inputs like n=4

迷宫问题

在二维数组中为您提供了一个大小为N * N的矩阵,其源位置为(0,0),目标位置为(N-1,N-1)。 数组中的某些位置被标记为0,它们是受阻止的单元格,其余位置被标记为1。

路径是从(0,0)到(N-1,N-1)的由1组成的元素的连接序列。如果序列中的每个1相邻,则2D数组中的1s序列将被连接(以上或左邻居)到序列中的下一个1。

例如,在以下矩阵中,

1 1 0
0 1 1
1 0 1 

蓝色标记的1是从(0,0)到(2,2)的连接路径

请注意,(0,0)和(N-1,N-1)的像元始终为1。您可以向右或向下移动,即从位置(x,y)可以移至任一位置(x,y + 1)或(x + 1,y)。

输入

第一行由输入数组N的大小(<= 50)组成,其后是NxN迷宫的状态,由0和1组成。

产量

如果源和目标之间存在路径,则必须打印“可能”,否则请打印“不可能”。

有问题的情况

对于以下输入,

4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

控制台显示NOT POSSIBLE,而正确的输出应该是POSSIBLE

C代码

#include<stdio.h>

#define true 1
#define false 0
// Maze size
int N;

int solveMazeUtil(int maze[N][N], int x, int y, int sol[N][N]);

/* A utility function to print solution matrix sol[N][N] */
void printSolution(int sol[N][N])
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
            printf(" %d ", sol[i][j]);
        printf("\n");
    }
}

/* A utility function to check if x,y is valid index for N*N maze */
int isSafe(int maze[N][N], int x, int y)
{
    // if (x,y outside maze) return false
    if(x >= 0 && x < N && y >= 0 && y < N && maze[x][y] == 1)
        return true;

    return false;
}

/* This function solves the Maze problem using Backtracking.  It mainly uses
solveMazeUtil() to solve the problem. It returns false if no path is possible,
otherwise return true and prints the path in the form of 1s. Please note that
there may be more than one solutions, this function prints one of the feasible
solutions.*/
int solveMaze(int maze[N][N])
{
    int sol[N][N] = { {0, 0, 0, 0},
        {0, 0, 0, 0},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    };

    if(solveMazeUtil(maze, 0, 0, sol) == false)
    {
        printf("NOT POSSIBLE");
        return false;
    }
printf("POSSIBLE");
   // printSolution(sol);
    return true;
}

/* A recursive utility function to solve Maze problem */
int solveMazeUtil(int maze[N][N], int x, int y, int sol[N][N])
{
    // if (x,y is goal) return true
    if(x == N-1 && y == N-1)
    {
        sol[x][y] = 1;
        return true;
    }

    // Check if maze[x][y] is valid
    if(isSafe(maze, x, y) == true)
    {
        // mark x,y as part of solution path
        sol[x][y] = 1;

        /* Move forward in x direction */
        if (solveMazeUtil(maze, x+1, y, sol) == true)
            return true;

        /* If moving in x direction doesn't give solution then
           Move down in y direction  */
        if (solveMazeUtil(maze, x, y+1, sol) == true)
            return true;

        /* If none of the above movements work then BACKTRACK: 
            unmark x,y as part of solution path */
        sol[x][y] = 0;
        return false;
    }   

    return false;
}

// driver program to test above function
int main()
{
    int n;
    scanf("%d",&n);
    N=n;
    int maze[52][52]  ;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            scanf("%d",&maze[i][j]);
        }
    solveMaze(maze);
    return 0;
}

通过更改使N为变量,您的代码几乎是正确的。 您只是忽略了其中一个硬编码为52而不是N的地方:

int maze[52][52]; 应该是int maze[N][N];

编译器应该警告您的另一件事是该行:

int sol[N][N] = {  // etc.

不允许:可变长度数组可能没有初始化程序。 您将需要通过循环或通过memset(需要#include <string.h> )进行初始化:

int sol[N][N];
memset(&sol, 0, sizeof sol);

进行这些更改之后,您的代码对我来说有些简单的迷惑。


还有一个不同的问题。 您的迷宫求解算法无法应对必须先降后高(或先右后左)的迷宫。 因此它适用于任何4x4迷宫,但不适用于此迷宫:

5
1 0 1 1 1
1 0 1 0 1
1 0 1 0 1
1 1 1 0 1
0 0 0 0 1

但是,您的问题描述似乎定义了该路径只能向右或向下移动。 因此,在这种情况下,您的代码将能够解决所有必需的迷宫。 也许作为一项额外的练习,您可以更新代码,以解决像我刚刚发布的这样的迷宫:)

这是一个非常有趣的问题,可以方便地进行动态编程。 实际上,这是我在有人问我什么是动态编程时使用的示例。

现在,这里是值得考虑的问题:

如果一个单元格为0,是否仍有可能到达该单元格?

如果一个单元格为1,您怎么知道可以到达此单元格? 您可以使用哪些不同的方式到达该单元格?

第一个问题很明显。 如果单元格为0,则无法访问。

第二个问题并非如此,但仍然非常简单:可以通过两种方式到达一个单元:从其上方 的单元左侧的单元

既然我们已经进行了观察,我们知道给定最后一个单元格(N-1,N-1),我们知道在以下情况下可以到达该单元格:

  1. 单元格为1 &&
  2. 可以到达上方的单元格或左侧的单元格。

递归地,如果当前单元格为1,则可以通过递归调用两个单元格来最终找出是否存在这样的路径。


现在,这不是很有效。 在所有单元格均为1的最坏情况下,复杂度是指数级的。 我们如何做得更好?

迷宫的第一列和第一行呢? 什么时候可以到达?

第一行中的单元格/列只能以一种方式达到(想象排-1和col -1充满0),因为我们知道在单元格(0,0)为1,我们可以反复发现的可达性第一行/列中的所有单元格。 使用第一行/列,您可以对第二行/列执行相同的操作!

换句话说,一行的状态取决于它上面的行; 一列的状态取决于其左列。 根据定义,我们已经有row / col -1,其余的可以在O(n ^ 2)中逐行迭代地计算。

我故意不提供代码,因为思考过程在这里可能更有价值。 希望有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM