DFS
首先先看下面这个有关迷宫的问题引入思考。
Description
每天刷题太枯燥了,为了放松一下自己,你,zjx和hhy约好了周末一起去玩密室逃脱。一般的密室逃脱对你们没有什么吸引力了,所以你们找到了一个更好玩的密室逃脱。
我们可以把整个密室看成一个 n * m 的网格图(包含很多房间),其中每个房间都是一个1 * 1的单元格, 有一些房间有机关,进入后会失去游戏资格。我们将没有机关的房间用0表示,有机关的房间用1表示。
迷宫的规则是开局的时候zjx和hhy被随机放到一个房间里(保证被放房间是没有机关的),单位时间内他们可以选择进入到相邻的房间(上下左右),也可以选择不动。两人相遇即可通过游戏,越短时间通过游戏获得的奖品越好,所以你们要在最短的时间通过游戏,触碰机关失去游戏资格不会获得奖品。你在密室外指挥他们从自己的起点出发使他们相遇(你可以看到迷宫的地图并且你们之间可以联系),现在请你计算出他们两个从出发点到相遇需要的最短时间。
Input
第一行两个整数n, m表示网格图的大小。
第二行四个整数x1, y1, x2, y2分别表示zjx和hhy的起点横纵坐标。
接下来一个矩阵:n行,每行m个数(只含0和1),表示地图。
1 <= n, m <= 100, 1 <= x1, x2 <= n, 1 <= y1, y2 <= m
Output
一行,一个整数,表示zjx和hhy相遇的最短时间。
思路:
一看题目很多的字,但是其实你耐心读下去,提取信息会发现很简单,就是两个憨憨一起走一个迷宫,俩人都有自己的初始位置,他们同时走,每走一步都消耗一样的单位时间。然后问他们俩相遇的最短时间。
我们简化问题,两个人同时走让你不好思考,那你就把问题转化为一个人不动,然后另一个人来找这个人的最短路max_sum径是多少(因为走单位格移动的时间是单位时间,换成求路径更方便你思考),之后这个max_sum再除以2就是他们俩同时走的时间了。(当然,你思考一下,直接除以2是完全正确的吗?)
当然不是的了,因为两个人之间的最优路线的路径是奇数的话,那么势必有一个人要多走一步,判断一下加一即可,是偶数的时候便直接除以2.
下面开始讲核心算法DFS/BFS.
BFS
相当于一个队列,队列没学好的可以看下队列的基本知识便可以更好理解BFS的运用。
首先是存图,可以用最简单的二维表(二维数组)的方式存一个图。循环嵌套存入地图,应该不用过多讲解了。之后是定义一个队列,这个队列你可以自己手动写一个,也可以直接用STL里的queue队列。接着是一个循环,每次都要处理队列头的位置,寻找出这个位置能走到的所有位置,把更新出来的位置入队。之后删掉表头。这样就可以实现“千军万马”地毯式搜索的效果了。
例如此时队列头的位置在start(2,1),
1 | start | |
1 | ||
1 | ||
end |
那么你下一步可以走的位置可以是(1,2),(2,3),(3,2),(2,1)有障碍物不能走。
here | ||
---|---|---|
1 | start | here |
here | ||
1 | ||
1 | ||
end |
你可能会疑惑如何让他判断所有下一步能走的点,你需要定义一个位置数组,这里我习惯定义一个nest数组,nest[4][2]={ {0,1},{1.0},{0,-1},{-1,0} },也就是说循环一下就会每次依次默认向右,下,左,上,进行试探搜索。比方说startx=2,starty=1,那么下一步向右t,x=2+0=2,ty=1+1=2,(2,2)没有障碍物,可以走,把这个位置入队,你可以思考一下整个搜索的过程,如果地图没问题,最先搜索到的目的位置的那条线也就是最短距离,也就是你要找的答案。
(DFS和BFS的具体实践等有空再更,你可以试着直接写一下DFS/BFS试一试)
代码如下:
#include <iostream>
#include <stdio.h>
using namespace std;
int n,m,map[401][401]={0},book[401][401]={0};
struct node{
int x;
int y;
int step;
};
int nest[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
node queue[160001];
int main()
{
int i,j,head,tail,a,b,tx,ty,x1,y1,x2,y2;
cin>>n>>m>>x1>>y1>>x2>>y2;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>map[i][j];
}
}
head=1;
tail=1;
queue[tail].x=x1;
queue[tail].y=y1;
queue[tail].step=0;
book[x1][y1]=1;
tail++;
while(head!=tail)
{
for(i=0;i<4;i++)
{
tx=queue[head].x+nest[i][0];
ty=queue[head].y+nest[i][1];
if(tx>n||ty>m||tx<1||ty<1)
{
continue;
}
if(book[tx][ty]==0&&map[tx][ty]==0)
{
queue[tail].x=tx;
queue[tail].y=ty;
queue[tail].step=queue[head].step+1;
book[tx][ty]=1;
if(tx==x2&&ty==y2)
{
if(queue[tail].step%2==0)
{
cout<<queue[tail].step/2<<endl;
break;
}
else
cout<<queue[tail].step/2+1<<endl;
break;
}
tail++;
}
}
head++;
}
cout<<endl;
return 0;
}