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
#include
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 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
Stack::Stack(int stackCpacity)//构造函数
{
	capacity = stackCpacity;
	if (capacity < 1) throw"stack capackty must be > 0";
	stack = new T[capacity];
	top = -1;
}
template
inline bool Stack::IsEmpty()
{
	return top == -1;
}
template
inline T& Stack::Top()
{
	if (IsEmpty())throw"Stack is empty";
	return stack[top];
}
template
void Stack::Push(const T&x)
{
	stack[++top] = x;
}
template
void Stack::Pop()
{
	if (IsEmpty())throw"Stack is empty. Cannot delete.";
	stack[top--] = 0;
}
template
void Stack::Delete() {
	if (stack)
		delete[]stack;
}
Items t(1, 1, N);//初始位置和方向
Stack 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

你可能感兴趣的:(数据结构)