数据结构实训四——图的操作
1.实验目的:
(1)掌握回溯算法;
(2)掌握图的深度优先和广度优先搜索算法并用来解决实际问题;
2. 实验内容:
迷宫求解:以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。要求如下:
(1)首先实现一个栈类型,利用回溯法求解迷宫路径(非递归程序)。求得的通路以三元组(i,j,d)的形式输出,其中(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
(2)建立图的存储结构,利用深度优先搜索,求得迷宫路径。输出方式自行定义,简单清晰则可。
(3)利用广度优先搜索,求得迷宫路径。输出方式自行定义,简单清晰则可。
(4)假如有多条路径,如何求最短的那一条路径?
3.实验代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int mp[110][110];
struct node
{
int x,y;
string dir;
};
bool check(node t)///判断某个节点是否可以走
{
int x=t.x,y=t.y;
if(x>=1&&x<=n&&y>=1&&y<=m&&!mp[x][y]) return 1;
return 0;
}
void init()
{
///输入迷宫
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin>>mp[i][j];
}
void findpath1()///非递归求解迷宫路径
{
stack<node>stk;
node now= {1,1,"0"};
stk.push({1,1,"0"});
while(!stk.empty())
{
node t=stk.top();
if(t.x==n&&t.y==m)
{
break;
}
node ne=t;
mp[t.x][t.y]=2;
ne=t;
ne.x--;
if(check(ne))
{
t.dir="up";
stk.pop();
stk.push(t);
stk.push(ne);
continue;
}
ne=t;
ne.x++;
if(check(ne))
{
t.dir="down";
stk.pop();
stk.push(t);
stk.push(ne);
continue;
}
ne=t;
ne.y--;
if(check(ne))
{
t.dir="left";
stk.pop();
stk.push(t);
stk.push(ne);
continue;
}
ne=t;
ne.y++;
if(check(ne))
{
t.dir="right";
stk.pop();
stk.push(t);
stk.push(ne);
continue;
}
t=stk.top();
stk.pop();
mp[t.x][t.y]=3;
}
vector<node>v;
while(!stk.empty())
{
v.push_back(stk.top());
stk.pop();
}
reverse(v.begin(),v.end());
for(int i=0; i<v.size(); i++) cout<<v[i].x<<" "<<v[i].y<<" "<<v[i].dir<<endl;
}
stack<node>path,tmp;
int nx[]= {0,0,1,-1};
int ny[]= {1,-1,0,0};
int vis[110][110];
int cnt=0;
void findpath2(int x,int y) ///dfs求解迷宫所有路径
{
if(x==n&&y==m)
{
cout<<"***************路径"<<++cnt<<"*****************"<<endl;
while(!path.empty())
{
tmp.push(path.top());
path.pop();
}
while(!tmp.empty())
{
cout<<"("<<tmp.top().x<<","<<tmp.top().y<<")"<<endl;
path.push(tmp.top());
tmp.pop();
}
return ;
}
if(x<1||x>n||y<1||y>m) return ;
for(int i=0; i<4; i++)
{
int xx=x+nx[i],yy=y+ny[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!mp[xx][yy]&&vis[xx][yy]==0)
{
vis[xx][yy]=1;
path.push({xx,yy});
findpath2(xx,yy);
vis[xx][yy]=0;
path.pop();
}
}
}
queue<node>q;
int dis[110][110],fx[110][110],fy[110][110];
void Prinpath3(int x,int y)///bfs打印路径 递归打印
{
if(x!=-1&&y!=-1)
{
Prinpath3(fx[x][y],fy[x][y]);
cout<<"("<<x<<","<<y<<")"<<endl;
}
}
void findpath3()///bfs求解最短路径
{
memset(dis,-1,sizeof dis);///初始化距离数组
q.push({1,1});///将起始点放入队列
dis[1][1]=0;///初始化距离
fx[1][1]=fy[1][1]=-1;///表示这个点的上一个点的坐标
while(!q.empty())
{
node now=q.front();
q.pop();
for(int i=0; i<4; i++)
{
node nex;
nex.x=now.x+nx[i],nex.y=now.y+ny[i];
if(check(nex)&&dis[nex.x][nex.y]==-1)
{
q.push(nex);
dis[nex.x][nex.y]=dis[now.x][now.y]+1;
fx[nex.x][nex.y]=now.x;
fy[nex.x][nex.y]=now.y;
}
}
}
Prinpath3(n,m);
}
int main()
{
init();
//findpath1();
// findpath2(1,1);
findpath3();
return 0;
}
/*
3 3
0 1 1
0 1 1
0 0 0
*/