2

私は、迷路をうまく通り抜けることができる再帰的な迷路ソルバーアルゴリズムを持っています。唯一の問題は、始点と終点の間の最短経路を保存する方法が見つからないことです。最短経路の座標を保存するにはどうすればよいですか?

これが再帰関数です

void Solve_Maze(int coorx,int coory) {
    if((coorx>=0)&&(coorx<l)&&(coory>=0)&&(coory<w)) {
        if((Map[coorx][coory]==Start)||(Map[coorx][coory]==path)) {
            Map[coorx][coory]=visited;
            Solve_Maze(coorx+1,coory);
            Solve_Maze(coorx-1,coory);
            Solve_Maze(coorx,coory+1);
            Solve_Maze(coorx,coory-1);
        }else if(Map[coorx][coory]==End) {
            delete Map;
            Solved=true;
        }
    }
}

座標を格納するためのベクトルを追加した後、この出力を得ました

(1,2)
(2,2)
(3,2)
(4,2)
(5,2)
(6,2)
(7,2)
(8,2)
(9,2)
(7,3)
(7,4)
(7,5)
(7,6)
(8,6)
(8,7)
(9,7)
(10,7)

すべての座標を保存しますが、取りたくないパスの座標も保存します ((7,2)(8,2)(9,2) から (7,3) に戻る)。最短パスを保存するだけで保存できる方法はありますか?

4

2 に答える 2

2

ベクトルを使用してソリューション座標を追跡する方法は次のとおりです。

#include <iostream>
#include <vector>
#include <map>

using namespace std;

const int w = 10, l = 10;
const char Start = 'S', Path = ' ', End = 'E', Visited = '.', Solution = '*';

char Map[w][l + 1] =
{
    { "  #  # #  " },
    { " S   #  # " },
    { " ###      " },
    { "   #   #  " },
    { "    #   # " },
    { "#        #" },
    { "    ###   " },
    { "  ##E ##  " },
    { "  #       " },
    { "   ##### #" },
};

int Solved = false;
vector<pair<int,int> > SolutionCoors;

void PrintMap()
{
    int x, y;

    for (y = 0; y < w; y++)
    {
        for (x = 0; x < l; x++)
            cout << Map[y][x];

        cout << endl;
    }
}

void Solve_Maze(int CoorX, int CoorY)
{
    if (CoorX >= 0 && CoorX < l && CoorY >= 0 && CoorY < w && !Solved)
    {
        SolutionCoors.push_back(make_pair(CoorX, CoorY)); // Store potential solution

        if (Map[CoorY][CoorX] == Start || Map[CoorY][CoorX] == Path)
        {
            Map[CoorY][CoorX] = Visited;

            Solve_Maze(CoorX + 1, CoorY);
            Solve_Maze(CoorX - 1, CoorY);
            Solve_Maze(CoorX, CoorY + 1);
            Solve_Maze(CoorX, CoorY - 1);
        }
        else if (Map[CoorY][CoorX] == End)
            Solved = true;

        if (!Solved)
            SolutionCoors.pop_back();
    }
}

int main()
{
    PrintMap();

    Solve_Maze(1, 1);

    if (Solved)
    {
        for (vector<pair<int,int> >::iterator it = SolutionCoors.begin();
             it != SolutionCoors.end();
             it++)
        {
            cout << "(" << it->first << "," << it->second << ")" << endl; // Print solution coords
            Map[it->second][it->first] = Solution; // Also mark on the map
        }

        PrintMap();
    }

    return 0;
}

出力:

  #  # #  
 S   #  # 
 ###      
   #   #  
    #   # 
#        #
    ###   
  ##E ##  
  #       
   ##### #
(1,1)
(2,1)
(3,1)
(4,1)
(4,2)
(5,2)
(6,2)
(6,3)
(5,3)
(5,4)
(6,4)
(7,4)
(7,5)
(8,5)
(8,6)
(9,6)
(9,7)
(8,7)
(8,8)
(7,8)
(6,8)
(5,8)
(4,8)
(4,7)
  #  #.#..
 ****#..#.
 ###***...
   #.**#..
    #***#.
#      **#
    ### **
  ##* ##**
  #.*****.
   ##### #

Map[][]また、座標が逆になっていることに注意してください。

于 2012-05-20T06:49:56.113 に答える
0

現在のパスの長さが以前に保存されたパスの長さよりも小さい場合は、スタックを明示的にする必要があります。現在はプロシージャSolve_Maze呼び出しで暗黙的であり、 に達したときにスタックからソリューション ベクトルにコピーします(存在する場合)。Solved=trueもちろんcoorx,coory、プロシージャに入るときにプッシュし、終了するときにポップします(状態の変化は気にしません)。

タイプ「スタック」の場合の外部変数 (標準ライブラリを使用しない場合は配列を使用できます) 以外に、構造体で coorx,coory を結合し、Solve_Maze に割り当てられたときにそれらへのポインターを渡すことができます。しかし、これによりコードが大幅に変更されます。スタックを渡す方がはるかに簡単です...

于 2012-05-20T05:35:56.017 に答える