您的位置:首页 > 理论基础 > 数据结构算法

数据结构作业 迷宫问题 模拟 之基础的BFS DFS

2009-10-05 22:50 423 查看
题目要求老鼠Pzjay从(1,1)出发,到达右下角(或指定位置)是否有路径(DFS),并求最短路径(BFS),DFS是顺序输出路径的,而BFS是逆序输出的(改成顺序输出EASY,就不改了)。貌似DFS也能求最佳路径,但代码量比较可观,BFS!

求最短路径dfs也可以,不过ms麻烦哩狠狠,故而bfs代替之。为何bfs找到的就是最佳路径呢,据leefour讲:因为

每次入列的均是上个走过的坐标的最近点,并且宽搜是遍历完当前所有入列的点(即八个方向的坐标)后才探寻下一步

,不同于dfs的一条道走到死才回头,所以dfs找到的路径是随机的,而bfs则是最短路径,Orz。
放码子:


//dfs版:
#include<iostream>
#include<deque>
#define nax 100
using namespace std;
typedef struct mi
{
int x;
int y;
}pzjj;
int line,col,num=0;
int maze[nax][nax];
int dir[8][2] ={-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};
pzjj mouse[nax];
bool dfs(int a,int b)//dfs最好返回bool值,容易处理
{
mouse[num].x=a;
mouse[num].y=b;//将当前坐标记录
num++;
if(a==line && b==col)
return true;
int i;
int lx,ly;
for(i=0;i<8;i++)
{
lx=a+dir[i][0];
ly=b+dir[i][1];
if((lx<=line && ly<=col && lx>0 && ly>0) && maze[lx][ly]==1)
{
maze[lx][ly]=0;//标记走过
int _t = num;//记录下当前num值
bool t = dfs(lx,ly);
if(t)//如果走得通或到达终点
return true;
num = _t;//否则num回到dfs之前的值
maze[lx][ly]=1;//撤销标记
}
}
return false;//走到此说明此路不通
}
int main()
{
int i,j;
scanf("%d%d",&line,&col);
memset(maze,0,sizeof(maze));
for(i=1;i<=line;i++)
for(j=1;j<=col;j++)
scanf("%d",&maze[i][j]);//1表示通过,0表示障碍
if(!dfs(1,1))
{
printf("死路/n");
return false;
}
for(i=0;i<num;i++)
printf("%d %d/n",mouse[i].x,mouse[i].y);
return false;
}
//bfs版:其输出的路径是倒叙的
#include<iostream>
using namespace std;
int dir[8][2] ={-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};
int maze[100][100];
typedef struct pp
{
int x,y,pre;
}pzjj;
pzjj mouse[100];
void display(int tail)
{
int i=tail;
do
{
printf("%d %d/n",mouse[i].x,mouse[i].y);
i=mouse[i].pre;
}while(i!=0);
}
void bfs(int line,int col)
{
int i,lx,ly;
bool find=false;
int front=1,rear=1;
mouse[1].x=1,mouse[1].y=1,mouse[1].pre=0;//初始化,从1,1开走
while(front<=rear && !find)
{
for(i=0;i<8;i++)//开始搜
{
lx=mouse[front].x+dir[i][0];
ly=mouse[front].y+dir[i][1];
if(maze[lx][ly]==1)
{
rear++;
mouse[rear].x=lx;
mouse[rear].y=ly;
mouse[rear].pre=front;
maze[lx][ly]=0;//标记走过
}
if(lx==line && ly==col)
{
display(rear);
find=true;
}
}
front++;
}
if(!find)
printf("死路/n");
}
int main()
{
int i,j;
int col,line;
scanf("%d%d",&line,&col);
memset(maze,0,sizeof(maze));
for(i=1;i<=line;i++)
for(j=1;j<=col;j++)
scanf("%d",&maze[i][j]);//1表示通过,0表示障碍
bfs(line,col);
return false;
}

后来小慧姐让灰得让用栈写这个迷宫求解,补一个栈模拟递归的:
#include<iostream>
#include<stack>
using namespace std;
const int sup=200;
const int dir[4][2]={0,1,1,0,-1,0,0,-1};
struct Pzjay//
{
int x;
int y;
void operator=(const Pzjay &tmp)
{
this->x=tmp.x;
this->y=tmp.y;
};
bool operator==(const Pzjay &b)
{
return (this->x==b.x && this->y==b.y);
};
}path[sup][sup];//path[i][j]记录一条路径上(i,j)位置的前一个位置
bool used[sup][sup];
int matr[sup][sup];
Pzjay beg,end;
stack <Pzjay> st;
bool dfs(int row,int column,int &sum)
{
int i,j;
st.push(beg);
Pzjay top,temp;
while(!st.empty())//栈不空继续探索
{
top=st.top();
st.pop();
used[top.x][top.y]=true;
if(top==end)
return true;
for(i=0;i<4;++i)//探索四个方向是否可以通行
{
temp.x=top.x+dir[i][0];
temp.y=top.y+dir[i][1];
if(!used[temp.x][temp.y] && matr[temp.x][temp.y])//没访问过并且是通路
{
st.push(temp);
path[temp.x][temp.y]=top;
}
}
}
return false;
}
int main()
{
int R;
int C;
int sum=0;//记录路径步数
memset(matr,0,sizeof(matr));
memset(used,false,sizeof(used));
scanf("%d%d",&R,&C);//输入迷宫行数列数
int i,j;
for(i=1;i<=R;++i)
for(j=1;j<=C;++j)
scanf("%d",&matr[i][j]);//matr[i][j]=1表示此处可以通行,matr[i][j]=0表示此处不通
beg.x=beg.y=1;
end.x=R;
end.y=C;
if(dfs(R,C,sum))
{
printf("Bingo/n");
do
{
printf("%d %d/n",end.x,end.y);
end=path[end.x][end.y];//从终点倒溯回去
}while(end.x!=beg.x || end.y!=beg.y);
cout<<end.x<<" "<<end.y<<endl;
}
else
printf("No way!/n");
return 'Pz';
}

双广版:
#include<iostream>
using namespace std;
const int sup=505;
const int dir[4][2]={0,1,1,0,-1,0,0,-1};
struct maze
{
int x;
int y;
void operator=(const maze &tmp)
{
this->x=tmp.x;
this->y=tmp.y;
};
bool operator==(const maze &b)
{
return (this->x==b.x && this->y==b.y);
};
}stack[sup*sup];//path[sup][sup];//path[i][j]??????????????(i,j)????????????????
int used[sup][sup];
int matr[sup][sup];
maze beg,end;
bool Hot_Girl(int row,int column)
{
int i,j,head(0),tail(0);
stack[tail++]=beg;
stack[tail++]=end;
used[beg.x][beg.y]='P';
used[end.x][end.y]='z';
maze top,temp;
while(head<tail)//??????????????
{
top=stack[head++];
head%=(row*column);
tail%=(row*column);
/*if(used[top.x][top.y]==122)
cout<<"top "<<num<<" "<<top.x<<" "<<top.y<<endl;*/
for(i=0;i<4;++i)//????????????????????????
{
temp.x=top.x+dir[i][0];
temp.y=top.y+dir[i][1];
if(matr[temp.x][temp.y])//??????????????????
{
if(0==used[temp.x][temp.y])
{
used[temp.x][temp.y]=used[top.x][top.y];
stack[tail++]=temp;
}
else if(used[temp.x][temp.y]!=used[top.x][top.y])
return true;
}
}
}
return false;
}
int main()
{
int R;
int C;
for(int i=0;i<sup;++i)
fill(used[i],used[i]+sup,0);
//freopen("1.txt","r",stdin);
memset(matr,0,sizeof(matr));
scanf("%d%d",&R,&C);//????????????????
int i,j;
for(i=1;i<=R;++i)
for(j=1;j<=C;++j)
scanf("%d",&matr[i][j]);//matr[i][j]=1??????????????????matr[i][j]=0????????????
beg.x=beg.y=1;
end.x=R;
end.y=C;
if(Hot_Girl(R,C))
{
printf("Bingo/n");
//do
//{
//	pzj[end.x][end.y]='@';
//	//printf("%d %d/n",end.x,end.y);
//	end=path[end.x][end.y];//??????????????
//}while(end.x!=beg.x || end.y!=beg.y);
//pzj[end.x][end.y]='@';
//freopen("out.txt","w",stdout);
//for(i=1;i<=R;++i)
//{
//	for(j=1;j<=C;++j)
//		printf("%c ",pzj[i][j]);
//	printf("/n");
//}
////cout<<end.x<<" "<<end.y<<endl;
}
else
printf("No way/n");
return 0;
}


不系本人自恋,实在是有些无耻的站点不啃声就把码字拿走了,然后装的极其若无其事

附测试数据:

7 8
1 0 0 0 0 0 1 0
1 0 0 0 0 1 0 1
1 0 0 0 1 0 0 1
1 0 0 0 0 1 0 1
1 0 1 0 1 0 0 1
0 1 0 1 0 0 1 0
0 0 0 0 0 0 0 1

answer:
1 1
2 1
3 1
4 1
5 1
6 2
5 3
6 4
5 5
4 6
3 5
2 6
1 7
2 8
3 8
4 8
5 8
6 7
7 8

这个目测就知道是否正确,不给答案了!

4 4
1 0 0 1
0 1 0 1
1 0 1 1
0 1 1 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: