c++编迷宫设置通路的思路

c++编迷宫设置通路的思路,第1张

#include<iostream>

using namespace std;

class T //定义描述迷宫中当前位置的结构类型

{

public:

int x; //x代表当前位置的行坐标

int y; //y代表当前位置的列坐标

int dir; //0:无效,1:东,2:南,3:西,4:北

};

class LinkNode //链表结点

{

friend class Stack;

public:

T data;

LinkNode next;

};

class Stack

{

private:

LinkNode top; //指向第一个结点的栈顶指针

public:

Stack(); //构造函数,置空栈

~Stack(); //析构函数

void Push(T e); //把元素data压入栈中

T Pop(); //使栈顶元素出栈

T GetPop(); //取出栈顶元素

void Clear(); //把栈清空

bool empty(); //判断栈是否为空,如果为空则返回1,否则返回0

};

Stack::Stack() //构造函数,置空栈

{

top=NULL;

}

Stack::~Stack() //析构函数

{

}

void Stack::Push(T e) //把元素x压入栈中

{

LinkNode P;

P=new LinkNode;

P->data=e;

P->next=top;

top=P;

}

T Stack::Pop() //使栈顶元素出栈

{

T Temp;

LinkNode P;

P=top;

top=top->next;

Temp=P->data;

delete P;

return Temp;

}

T Stack::GetPop() //取出栈顶元素

{

return top->data;

}

void Stack::Clear() //把栈清空

{

top=NULL;

}

bool Stack::empty() //判断栈是否为空,如果为空则返回1,否则返回0

{

if(top==NULL) return 1;

else return 0;

}

int move[4][2]=,,,}; //定义当前位置移动的4个方向

bool Mazepath(int maze,int m,int n);

//寻找迷宫maze中从(0,0)到(m,n)的路径

//到则返回true,否则返回false

void PrintPath(Stack p); //输出迷宫的路径

void Restore(int maze,int m,int n); //恢复迷宫

int GetMaze(int &m,int &n); //获取迷宫

//返回存取迷宫的二维指针

int main()

{

int m=0,n=0; //定义迷宫的长和宽

int maze; //定义二维指针存取迷宫

maze=GetMaze(m,n); //调用GetMaze(int &m,int &n)函数,得到迷宫

if(Mazepath(maze,m,n)) //调用Mazepath(int maze,int m,int n)函数获取路径

cout<<"迷宫路径探索成功!\n";

else cout<<"路径不存在!\n";

return 0;

}

int GetMaze(int &m,int &n)//返回存取迷宫的二维指针

{

int maze; //定义二维指针存取迷宫

int i=0,j=0;

cout<<"请输入迷宫的长和宽:";

int a,b;cin>>a>>b; //输入迷宫的长和宽

cout<<"请输入迷宫内容:\n";

m=a;

n=b; //m,n分别代表迷宫的行数和列数

maze=new int [m+2]; //申请长度等于行数加2的二级指针

for(i= 0;i<m+2;i++) //申请每个二维指针的空间

{

maze[i]=new int[n+2];

}

for(i=1;i<=m;i++) //输入迷宫的内容,0代表可通,1代表不通

for(j=1;j<=n;j++)

cin>>maze[i][j];

for(i=0;i<m+2;i++)

maze[i][0]=maze[i][n+1]=1;

for(i=0;i<n+2;i++)

maze[0][i]=maze[m+1][i]=1;

return maze; //返回存贮迷宫的二维指针maze

};

bool Mazepath(int maze,int m,int n)//寻找迷宫maze中从(0,0)到(m,n)的路径

//到则返回true,否则返回false

{

Stack q,p; //定义栈p、q,分别存探索迷宫的过程和存储路径

T Temp1,Temp2;

int x,y,loop;

Temp1x=1;

Temp1y=1;

qPush(Temp1); //将入口位置入栈

pPush(Temp1);

maze[1][1]=-1; //标志入口位置已到达过

while(!qempty()) //栈q非空,则反复探索

{

Temp2=qGetPop(); //获取栈顶元素

if(!(pGetPop()x==qGetPop()x&&pGetPop()y==qGetPop()y))

pPush(Temp2);

//如果有新位置入栈,则把上一个探索的位置存入栈p

for(loop=0;loop<4;loop++) //探索当前位置的4个相邻位置

{

x=Temp2x+move[loop][0]; //计算出新位置x位置值

y=Temp2y+move[loop][1]; //计算出新位置y位置值

if(maze[x][y]==0) //判断新位置是否可达

{

Temp1x=x;

Temp1y=y;

maze[x][y]=-1; //标志新位置已到达过

qPush(Temp1); //新位置入栈

}

if((x==(m))&&(y==(n))) //成功到达出口

{

Temp1x=m;

Temp1y=n;

Temp1dir=0;

pPush(Temp1); //把最后一个位置入栈

PrintPath(p); //输出路径

Restore(maze,m,n); //恢复路径

return 1; //表示成功找到路径

}

}

if(pGetPop()x==qGetPop()x&&pGetPop()y==qGetPop()y)

//如果没有新位置入栈,则返回到上一个位置

{

pPop();

qPop();

}

}

return 0; //表示查找失败,即迷宫无路经

}

void PrintPath(Stack p) //输出路径

{

cout<<"迷宫的路径为\n";

cout<<"括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向)\n";

Stack t; //定义一个栈,按从入口到出口存取路径

int a,b;

T data;

LinkNode temp;

temp=new LinkNode; //申请空间

temp->data=pPop(); //取栈p的顶点元素,即第一个位置

tPush(temp->data); //第一个位置入栈t

delete temp; //释放空间

while(!pempty()) //栈p非空,则反复转移

{

temp=new LinkNode;

temp->data=pPop(); //获取下一个位置

//得到行走方向

a=tGetPop()x-temp->datax; //行坐标方向

b=tGetPop()y-temp->datay; //列坐标方向

if(a==1) temp->datadir=1; //方向向下,用1表示

else if(b==1) temp->datadir=2; //方向向右,用2表示

else if(a==-1) temp->datadir=3; //方向向上,用3表示

else if(b==-1) temp->datadir=4; //方向向左,用4表示

tPush(temp->data); //把新位置入栈

delete temp;

}

//输出路径,包括行坐标,列坐标,下一个位置方向

while(!tempty()) //栈非空,继续输出

{

data=tPop();

cout<<'('<<datax<<','<<datay<<','<<datadir<<","; //输出行坐标,列坐标

switch(datadir) //输出相应的方向

{

case 1:cout<<"↓)\n";break;

case 2:cout<<"→)\n";break;

case 3:cout<<"↑)\n";break;

case 4:cout<<"←)\n";break;

case 0:cout<<")\n";break;

}

}

}

void Restore(int maze,int m,int n) //恢复迷宫

{

int i,j;

for(i=0;i<m+2;i++) //遍历指针

for(j=0;j<n+2;j++)

{

if(maze[i][j]==-1) //恢复探索过位置,即把-1恢复为0

maze[i][j]=0;

}

}

示例输出:

测试1:

请输入迷宫的长和宽:5 5

请输入迷宫内容:

0 1 1 0 0

0 0 1 1 0

1 0 0 1 1

1 0 0 1 0

1 1 0 0 0

迷宫的路径为

括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向)

(1,1,1,↓)

(2,1,2,→)

(2,2,1,↓)

(3,2,1,↓)

(4,2,2,→)

(4,3,1,↓)

(5,3,2,→)

(5,4,2,→)

(5,5,0,)

迷宫路径探索成功!

测试2:

请输入迷宫的长和宽:9 8

请输入迷宫内容:

0 0 1 0 0 0 1 0

0 0 1 0 0 0 1 0

0 0 0 0 1 1 0 1

0 1 1 1 0 0 1 0

0 0 0 1 0 0 0 0

0 1 0 0 0 1 0 1

0 1 1 1 1 0 0 1

1 1 0 0 0 1 0 1

1 1 0 0 0 0 0 0

迷宫的路径为

括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向)

(1,1,1,↓)

(2,1,1,↓)

(3,1,1,↓)

(4,1,1,↓)

(5,1,2,→)

(5,2,2,→)

(5,3,1,↓)

(6,3,2,→)

(6,4,2,→)

(6,5,3,↑)

(5,5,2,→)

(5,6,2,→)

(5,7,1,↓)

(6,7,1,↓)

(7,7,1,↓)

(8,7,1,↓)

(9,7,2,→)

(9,8,0,)

迷宫路径探索成功!

回溯可以理解成在岔路口选择不同的道路,直到达到目的地。它的每一步都会选择一条路出发,能前进都前进,不能前进就退到上一步,选择其他的路走,直到走完所有路或者到达目的地为止。 不能前进就退到上一步的过程就是回溯

典型的回溯应用有树、图的深度优先搜索、八皇后问题或者走迷宫等等。这里以八皇后的问题为例,来看一下回溯。

八皇后问题是在一个8X8的棋牌中放8个皇后,使其不能相互攻击,也就是任意两个皇后不能在同一行、同一列、同一斜率上。

解决八皇后问题,有这样几种思路,第一种就是暴力破解,从64个格子中选择出任意的8个格子摆放皇后,然后检查摆法是否合适,检查完每一种,需要检查的次数非常的大。

那么,可以根据题意来减少暴力破解的次数,因为 任意两个皇后不能在同一行 ,也就是每一行只能放一个皇后,所以摆放的次数就减少成 8^8^ 次。虽然次数减少了很多,但是次数还是比较多的。

最后一个思路就是用回溯法来处理,每次摆放皇后后,就将不能被摆放的格子给剔除掉,这种 *** 作叫做 剪切 。当到了无法摆放,并且皇后也没有摆放完时,就退回到最初摆放第一个皇后的位置,排除这个位置,从下一个位置开始,这个 *** 作叫做 回溯 。所以这个思路是 回溯+剪切

首先创建一个类,并定义数组,保存皇后摆放的位置 cols,cols 数组的索引对应的是第几行,从 0 开始,索引对应的元素是第几列,从 0 开始,也就是存储的数据是第几行中的第几列摆放了皇后,其次还定义一个属性 ways 记录有多少种摆法:

接下来创建摆放八皇后的函数,placeQueens(),函数中传递参数 n,表示摆放多少个皇后,让函数适应更多的同类场景,所以摆放八皇后就是 placeQueens(8),代码实现如下:

函数中先定义了 cols 数组的大小,有多少个皇后,就创建多少空间的数组。place() 函数执行的是摆放皇后的过程,传递的参数表示从第几行开始摆放,具体代码如下:

函数中可以看到 place(row+1) 这行代码,就是跳到下一行执行。当某行某列已经确定可以摆放皇后后,就暂时结束该行的遍历,跳到下一行执行。这里使用到递归思想, for 循环结束都是回溯的条件,如果没有达到终止条件,那么就会走 for 循环,当走完for 循环仍然没有找到可以摆放的位置时,然后执行 place(row+1) 上一行的代码,这就达到了 路不通,就回到上一步选择另外一条路 。isValid(row, col) 函数就是判断 (row, col) 的格子是否可以摆放皇后,代码如下:

这就是摆放皇后的核心部分。首先判断 col 列是否已经有皇后了,即遍历 cols 数组中是否存在 col 元素。如果不存在,就判断该 i 行的皇后和 (row, col) 区域的格子是否在同一斜率上,这里使用了斜率公式,x1-x2 = y1-y2 就是在同一斜率上,因为摆放的皇后,它的斜率就是 1。

var m,n,w,r,c,x:integer;

number:array[150,150]of char;

a,b,o,p:integer;

function count(z,y:integer):integer;

begin

number[z,y]:='$';

if (z=c)and(y=x) then exit;

if z<>1 then begin

if (number[z-1,y]<>'')and(number[z-1,y]='') then count(z+1,y);

end;

if z<>m then begin

if (number[z+1,y]<>'')and(number[z+1,y]='') then count(z-1,y);

end;

if y<>1 then begin

if (number[z,y-1]<>'')and(number[z,y-1]='') then count(z,y-1);

end;

if y<>n then begin

if (number[z,y+1]<>'')and(number[z,y+1]='') then count(z,y+1);

number[z,y]:='';

end;

end;

begin

assign(input,'1in');

assign(output,'2out');

reset(input);

rewrite(output);

readln(m,n);

readln(w,r);

readln(c,x);

for a:=1 to m do begin

if a<>1 then readln();

for b:=1 to n do read(number[a,b]);

end;

count(w,r);

for o:=1 to m do begin

writeln;

for p:=1 to n do write(number[o,p],' ');

end;

readln();

close(input);

close(output);

end

程西代码(报告自己写):

迷宫问题是指在mn的矩阵中,其中0表示“可以行走”的区域,1表示“不可行走”的区域,当你在迷宫的任何一个位置,除了不可行走的区域外,其余皆可以往上、右上、右、右下、下、左下、左、左上八个方向来走找出迷宫出口。/

/下面是65的迷宫,由于四边不可以走,所以定义成了87,输出中的2表示“已走过”区域,3表示“走过但未走通“区域”/

#include

<iostreamh>

int

Maze[8][7]=

{1,1,1,1,1,1,1,

1,0,1,0,0,0,1,

1,1,0,1,1,0,1,

1,1,0,1,1,0,1,

0,1,1,0,1,1,1,

1,0,0,1,0,1,1,

1,1,1,1,0,0,1,

1,1,1,1,1,1,1

};

//回溯法求迷宫问题

int

way(int

x,int

y)//x是行,y是列

{

if(Maze[6][5]==2)return

1;

else

if(Maze[x][y]==0)

{

Maze[x][y]=2;

if(way(x-1,y))return

1;

//上

else

if(way(x-1,y+1))return

1;//右上

else

if(way(x,y+1))return

1; //右

else

if(way(x+1,y+1))return

1;//右下

else

if(way(x+1,y))return

1; //下

else

if(way(x+1,y-1))return

1;//左下

else

if(way(x,y-1))return

1; //左

else

if(way(x-1,y-1))return

1;//左上

else {Maze[x][y]=3;

return

0;}

}

else

return

0;

}

//主函数

void

main()

{

int

i,j;

cout<<endl<<"

===迷宫问题==="<<endl<<endl;

//////////////////////////////////

//原图

cout<<"原图:"<<endl;

cout<<" 0 1 2 3 4 5 6"<<endl;

cout<<" +---+---+---+---+---+"<<endl;

for(i=0;i<8;i++)

{

cout<<"

"<<i<<"|";

for(j=0;j<7;j++)

cout<<"-"<<Maze[j]<<"-";

cout<<endl;

//

cout<<endl<<"

+---+---+---+---+---+---+"<<endl;

}

//////////////////////////////////

cout<<"入口:(1,1)"<<endl;

way(1,1);//从入口开始寻找出口

cout<<"走向图:"<<endl;

cout<<" 0 1 2 3 4 5 6"<<endl;

cout<<" +---+---+---+---+---+"<<endl;

for(i=0;i<8;i++)

{

cout<<"

"<<i<<"|";

for(j=0;j<7;j++)

cout<<"-"<<Maze[j]<<"-";

cout<<endl;

}

cout<<"出口:(6,5)"<<endl;

}

执行结果:

这个可以用 堆栈 来完成。

用堆栈的基本思路就是。

设置一个起点A。将 A 入栈 。

从A开始找到第一个可以达到的点B。将 B 入栈 。

如果B无路可走。则在A点处重新换一个可达到的点。否则继续 2-3 。直到达到终点。或者五路可走。

详细的解释,这儿有一篇博文:>

以上就是关于c++编迷宫设置通路的思路全部的内容,包括:c++编迷宫设置通路的思路、数据结构与算法-进阶(十七)回溯、pascal语言 有一个m*n的迷宫,老鼠从入口处(w, r)出发,经过设置了障碍的迷宫,最终到达出口处(c, x),请你编等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9619145.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存