簡體   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