c++迷宮問題回溯法遞迴演算法
c++迷宮問題回溯法遞迴演算法
本題採用棧和遞迴方法求解。(回溯法的概念請自行百度,簡而言之就是正常人走迷宮的思路,先走,遇到死路退回去)
迷宮被表示成為一個mxn的二維陣列,為了避免查詢邊界條件,我們用1包圍迷宮。這個陣列因此需要用maze[m+2][p+2]來宣告。老鼠在迷宮中任何時候的位置都能通過[i][j]表示。老鼠每次可以向八個方向移動,將其可能的方向預先定義在struct move中。
q | move[q].a | move[q].b |
---|---|---|
N | -1 | 0 |
NE | -1 | 1 |
E | 0 | 1 |
SE | 1 | 1 |
S | 1 | 0 |
SW | 1 | -1 |
W | 0 | -1 |
NW | -1 | -1 |
當前位置[i][j]的下一個座標[g][h]表示為:
g=i+move[SW].a; h=j+move[SW].b
使用另一個陣列mark[m+2][p+2]記錄老鼠已經走過的地方。
棧Stack定義為Items型別的棧,Items型別定義為:
struct Items{
int x,y,dir;
};
完整的程式如下
#include<iostream>
#include<stdlib.h>
using namespace std;
#define m 20
#define p 20
int maze[m + 2][p + 2];
int mark[m + 2][p + 2];
void setMaze() {//設定迷宮形狀並輸出
fill(maze[0], maze[0] + (m + 2)*(p + 2), 1);
fill(mark[0], mark[0] + (m + 2)*(p + 2), 0);
maze[0][0] = 0;
int i, j;
for (j = 1; j < 13; j++)maze[1][j] = 0;
for (i = 1; i < 10; i++)maze[i][13] = 0;
for (j = 7; j < p + 2; j++)maze[10][j] = 0;
for (j = 0; j < p + 2; j++) {
for (i = 0; i < m + 2; i++)cout << maze[i][j] << " ";
cout << endl;
}
}
struct offsets {//座標
int a, b;
};
enum directions { N, NE, E, SE, S, SW, W, NW };
struct Items {//棧的型別
int x, y, dir;
Items(int a = 0, int b = 0, int c = 0) {
x = a; y = b; dir = c;
}
void Print() {
cout << "(" << x << "," << y << ")" << ends;
}
};
template<class T>
class Stack
{
private:
int top, capacity;
public:
T*stack;//儲存棧元素的陣列
Stack(int stackCapacity = m*p);
bool IsEmpty();
T& Top();//返回棧頂元素
void Push(const T& item);//入棧
void Pop();//刪除棧頂元素
void Delete();
};
template<class T>
Stack<T>::Stack(int stackCpacity)//建構函式
{
capacity = stackCpacity;
if (capacity < 1) throw"stack capackty must be > 0";
stack = new T[capacity];
top = -1;
}
template<class T>
inline bool Stack<T>::IsEmpty()
{
return top == -1;
}
template<class T>
inline T& Stack<T>::Top()
{
if (IsEmpty())throw"Stack is empty";
return stack[top];
}
template<class T>
void Stack<T>::Push(const T&x)
{
stack[++top] = x;
}
template<class T>
void Stack<T>::Pop()
{
if (IsEmpty())throw"Stack is empty. Cannot delete.";
stack[top--] = 0;
}
template<class T>
void Stack<T>::Delete() {
if (stack)
delete[]stack;
}
Items t(1, 1, N);//初始位置和方向
Stack<Items> stack;
void path(Items temp) {
static offsets move[8] = { -1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1 };
int i = temp.x; int j = temp.y; int d = temp.dir;
if (d > NW) {//當前是死路
stack.Pop();
if (!stack.IsEmpty()) {
temp = stack.Top();
temp.dir++;
path(temp);
}
else cout << "not find";
}
int g = i + move[d].a; int h = j + move[d].b;
if ((g == m + 1) || (h == p + 1)) {//找到出口
cout << "find" << endl;
stack.Push(temp);
while (!stack.IsEmpty()) {
stack.Top().Print();
stack.Pop();
}
}
else if ((!maze[g][h]) && (!mark[g][h])) {//當前不是出口,依然能繼續走
stack.Push(temp);//路徑放入棧
mark[g][h] = 1;
temp.x = g; temp.y = h; temp.dir = N;
path(temp);//遞迴下一格
}
else//需要換方向
{
temp.dir++;
path(temp);//遞迴下一格
}
}
int main() {
setMaze();
path(t);
}
(第一次用,不會換顏色==)
程式結果:
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
find
(10,20) (10,19) (10,18) (10,17) (10,16) (10,15) (10,14)
(9,13) (8,13) (7,13) (6,13) (5,13) (4,13) (3,13) (2,13)
(1,13) (1,12) (1,11) (1,10) (1,9) (1,8) (1,7) (1,6) (1,5)
(1,4) (1,3) (1,2) (1,1)
(雖然這個迷宮看起來非常沙雕,但是好在比較清晰)
ps:
1.棧未新增解構函式
2.迷宮沒有出路的情況還沒有測試,可能會出現bug
3.迷宮列印的結果是倒敘,請自行從後向前讀。
4.提醒一下老鼠移動的方向有8個,是可以斜著走的。
and哪位好心人能告訴我顏色怎麼調TAT
相關文章
- 回溯法求迷宮問題
- 回溯和遞迴實現迷宮問題(C語言)遞迴C語言
- leetcode題解(遞迴和回溯法)LeetCode遞迴
- 遞迴與回溯法遞迴
- 迷宮問題
- 【dawn·資料結構】迷宮問題(C++)資料結構C++
- 資料結構和演算法——遞迴-八皇后問題(回溯演算法)資料結構演算法遞迴
- 使用A*演算法解迷宮最短路徑問題演算法
- (C++)資料結構實驗二——迷宮問題C++資料結構
- 遞迴加回溯遞迴
- POJ3984-迷宮問題
- 解密迷宮問題:三種高效演算法Java實現,讓你輕鬆穿越未知迷宮解密演算法Java
- 遞迴回溯相關遞迴
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- POJ3984 迷宮問題【BFS】
- 【LeetCode回溯演算法#08】遞增子序列,鞏固回溯演算法中的去重問題LeetCode演算法
- C#資料結構與演算法系列(十四):遞迴——八皇后問題(回溯演算法)C#資料結構演算法遞迴
- 「演算法之美系列」遞迴與回溯(JS版)演算法遞迴JS
- 遞迴問題遞迴
- Java資料結構與演算法--遞迴和回溯Java資料結構演算法遞迴
- 第七章 遞迴、DFS、剪枝、回溯等問題 ------------- 7.3 題解:機器人走方格問題遞迴機器人
- 簡單介紹Python迷宮生成和迷宮破解演算法Python演算法
- 洛谷 p1605 迷宮問題 詳解
- 迷宮問題——最短程式碼,不到70行
- 【大爽python演算法】遞迴演算法進化之回溯演算法(backtracking)Python演算法遞迴
- 遞迴-*全排列問題遞迴
- 遞迴路徑問題遞迴
- PARL原始碼走讀——使用策略梯度演算法求解迷宮尋寶問題原始碼梯度演算法
- 用python深度優先遍歷解迷宮問題Python
- 【力扣】排列問題(回溯法)(去重)力扣
- 回溯問題
- hdu2048遞迴問題遞迴
- hdu2049遞迴問題遞迴
- 樹遞迴問題的求解遞迴
- 從八皇后問題到回溯演算法演算法
- C++實現迷宮的生成與解決C++
- 走迷宮
- 1744 迷宮