简体   繁体   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

Maze problem 迷宫问题

You are provided a matrix of size N*N with source position at (0,0) and destination at (N-1,N-1) in a 2D array. 在二维数组中为您提供了一个大小为N * N的矩阵,其源位置为(0,0),目标位置为(N-1,N-1)。 Some of the positions in the array are marked as 0 which are blocked cells, rest being marked 1. 数组中的某些位置被标记为0,它们是受阻止的单元格,其余位置被标记为1。

A path is a connected sequence of elements from (0,0) to (N-1,N-1) which consists of 1. A sequence of 1s in the 2D array is connected if every 1 in the sequence is adjacent (the above or left neighbour) to the next 1 in the sequence. 路径是从(0,0)到(N-1,N-1)的由1组成的元素的连接序列。如果序列中的每个1相邻,则2D数组中的1s序列将被连接(以上或左邻居)到序列中的下一个1。

For example, in the following matrix, 例如,在以下矩阵中,

1 1 0
0 1 1
1 0 1 

the 1s marked in blue is a connected path from (0,0) to (2,2) 蓝色标记的1是从(0,0)到(2,2)的连接路径

Note that cells at (0,0) and (N-1,N-1) are always 1. You can either make movement towards right or down, ie, from position (x,y), you can go to either the position (x,y+1) or (x+1,y). 请注意,(0,0)和(N-1,N-1)的像元始终为1。您可以向右或向下移动,即从位置(x,y)可以移至任一位置(x,y + 1)或(x + 1,y)。

Input 输入

First line consists of the size of the input array N (<=50), following that would be the state of NxN maze which would consist of 0s and 1s. 第一行由输入数组N的大小(<= 50)组成,其后是NxN迷宫的状态,由0和1组成。

Output 产量

You have to print "POSSIBLE" if there exists a path between the source and the destination otherwise print "NOT POSSIBLE". 如果源和目标之间存在路径,则必须打印“可能”,否则请打印“不可能”。

Problematic cases 有问题的情况

For the following input, 对于以下输入,

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

The console displays NOT POSSIBLE whereas the correct output should be POSSIBLE . 控制台显示NOT POSSIBLE,而正确的输出应该是POSSIBLE

C Code 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;
}

With the change to make N be a variable, your code is nearly correct. 通过更改使N为变量,您的代码几乎是正确的。 You just overlooked one place where you had hardcoded 52 instead of N: 您只是忽略了其中一个硬编码为52而不是N的地方:

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

Another thing, which your compiler should have warned you about, is that the line: 编译器应该警告您的另一件事是该行:

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

is not allowed: variable-length arrays may not have initializers. 不允许:可变长度数组可能没有初始化程序。 You will need to initialize either via a loop or via memset (which needs #include <string.h> ): 您将需要通过循环或通过memset(需要#include <string.h> )进行初始化:

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

After making these changes, your code works for me on some simple mazes. 进行这些更改之后,您的代码对我来说有些简单的迷惑。


There is a different issue too; 还有一个不同的问题。 your maze solving algorithm can't cope with mazes where you have to go down then up (or right then left). 您的迷宫求解算法无法应对必须先降后高(或先右后左)的迷宫。 So it works for any 4x4 maze but it fails for this maze: 因此它适用于任何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

However, your problem description seems to define that the path should only ever move right or down. 但是,您的问题描述似乎定义了该路径只能向右或向下移动。 So, subject to that condition, your code will be able to solve all the required mazes. 因此,在这种情况下,您的代码将能够解决所有必需的迷宫。 Perhaps as an extra exercise you could update your code to be able to solve mazes like this one I have just posted :) 也许作为一项额外的练习,您可以更新代码,以解决像我刚刚发布的这样的迷宫:)

This is a very interesting problem where dynamic-programming comes handy. 这是一个非常有趣的问题,可以方便地进行动态编程。 In fact this is the example that I use whenever someone asks me what is dynamic programming. 实际上,这是我在有人问我什么是动态编程时使用的示例。

Now here are the questions that are worth considering: 现在,这里是值得考虑的问题:

If a cell is 0, is it still possible to reach this cell? 如果一个单元格为0,是否仍有可能到达该单元格?

If a cell is 1, how would you know that you could reach this cell? 如果一个单元格为1,您怎么知道可以到达此单元格? What are the different ways that you could use to get to this cell? 您可以使用哪些不同的方式到达该单元格?

The first question is obvious. 第一个问题很明显。 If a cell is 0 then it cannot be reached. 如果单元格为0,则无法访问。

The second question is less so, but still quite straightforward: a cell can be reached in two ways: from the cell above it or the cell to its left . 第二个问题并非如此,但仍然非常简单:可以通过两种方式到达一个单元:从其上方 的单元左侧的单元

Now that we have made these observation, we know that given the last cell (N-1, N-1), we know that it can be reached if: 既然我们已经进行了观察,我们知道给定最后一个单元格(N-1,N-1),我们知道在以下情况下可以到达该单元格:

  1. the cell is 1 && 单元格为1 &&
  2. the cell above or the cell to its left can be reached. 可以到达上方的单元格或左侧的单元格。

Recursively, we could eventually find out if there is such a path by recursively call the two cells if the current cell is 1. 递归地,如果当前单元格为1,则可以通过递归调用两个单元格来最终找出是否存在这样的路径。


Now, that's not very efficient. 现在,这不是很有效。 In the worst case where all cells are 1, the complexity is exponential. 在所有单元格均为1的最坏情况下,复杂度是指数级的。 How can we do better? 我们如何做得更好?

What about the first column and first row of the maze? 迷宫的第一列和第一行呢? When can they be reached? 什么时候可以到达?

Cells in the first row/column can only be reached in one way (imagine row -1 and col -1 are filled with 0) and as we know the cell (0,0) is 1, we can iteratively find out the reachability of all the cells in the first row/col. 第一行中的单元格/列只能以一种方式达到(想象排-1和col -1充满0),因为我们知道在单元格(0,0)为1,我们可以反复发现的可达性第一行/列中的所有单元格。 With first row/col, you could do the same for the second row/col! 使用第一行/列,您可以对第二行/列执行相同的操作!

In other words, the states of one row depends on the row above it; 换句话说,一行的状态取决于它上面的行; the states of one column depends on the column to its left. 一列的状态取决于其左列。 We already have the row/col -1 by definition, the rest can be computed iteratively, row by row, in O(n^2). 根据定义,我们已经有row / col -1,其余的可以在O(n ^ 2)中逐行迭代地计算。

I intentionally did not provide the code as the thought process is probably more valuable here. 我故意不提供代码,因为思考过程在这里可能更有价值。 Hope that helps! 希望有帮助!

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

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