0

有一个矩阵包含白色单元格(表示为 1)、黑色单元格(表示为 0)和只有一个灰色单元格(表示为 2),需要从 (0,0) 到 (N-1, N-1 ) 在数组[N][N] 中。

约束:

1) 路径应仅覆盖白色单元格,并且必须通过灰色单元格(此灰色单元格可以位于阵列中的任何位置)

2) 访问过的节点不能再访问。

以下是典型的迷宫问题解决方案,但此解决方案不处理遍历灰色单元的特定情况......所以请您帮我修改以下代码以处理具体情况。

我的问题是我不确定如何检查灰色单元格?

#include "stdafx.h"
#include "algorithm"
#include <iostream>
 #include <fstream>
using namespace std;
#include<stdio.h>

// Maze size
#define N 4 

bool 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 */
bool isSafe(int maze[N][N], int x, int y)
{
    //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
    if(x >= 0 && x < N && y >= 0 && y < N && maze[x][y] == 1)
        // if (x,y outside maze) return false
        return true;

    return false;
}

/* This function solves the Maze problem using Backtracking. It mainly uses
solutions.*/
bool 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("Solution doesn't exist");
        return false;
    }

    printSolution(sol);
    return true;
}

/* A recursive utility function to solve Maze problem */
bool 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 x 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 maze[N][N] = { {1, 0, 0, 0},
                       {1, 1, 0, 1},
                       {0, 1, 0, 0},
                       {1, 1, 1, 1}
                     };

    solveMaze(maze);
    getchar();
    return 0;
}

我在想的一种解决方案是:

生成所有可能的路径(遍历 1 或 2)。

然后,找出哪条路径中有 2。然后将该路径打印为输出。

但我不认为这将是一个好方法......所以,请让我知道如何以体面的方式实现我的目标。谢谢

4

2 回答 2

2

因为在您的代码中,您只使用了两种可能的移动:向下和向右,那么这是一个DAG。DAG 适用于动态规划方法:每个单元有两种可能到达那里,一种来自上方,另一种来自左侧。因此,一个单元的最小距离为:

cost[i][j] = min(cost[i][j-1],cost[i-1][j]) + 1

那是考虑到做一个运动的成本是1。如果单元格是黑色的,你可以给它一个无限的成本,你只需要找到一条从P1(start)到的路径P2(gray cell),然后找到一条从P2到的路径P3(goal)

为了重建路径,您可以创建另一个父母矩阵pi[N][N],如果最短路径来自上方,则如果无法到达该单元格,pi[i][j] = (i-1, j)则来自左侧。pi[i][j] = (i, j-1)pi[i][j] = null(whatever you want)

于 2013-10-20T16:49:41.453 回答
0

一般来说,我的方法是:

  1. 生成一个图,其中每个单元格都是一个顶点,并与代表迷宫中相邻的白色/灰色单元格的边顶点连接。
  2. P1找到起始顶点(表示 Array[0][0] 的那个)和灰色顶​​点(建议使用 A*)之间的最短路径。
  3. P2找到灰色顶点和结束顶点(表示 Array[N-1][N-1] 的那个)之间的最短路径。
  4. P1 和 P2 可能只相交一次(因为它们代表最短路径),如果它们相交,则从这一点开始,将代表同一条路径。因此:
    • 如果P1P2不相交,那么P1后面P2就是最优解。
    • ifP1P2do 相交,则删除相交部分的顶点,再次执行动作 2 和 3,分别找到新的最短路径P3P4。最优解是 和P1之间P4P3最小值P2
于 2013-10-20T14:27:44.203 回答