DFS是一条路走到黑,很多DFS模板题就是有关迷宫问题,迷宫问题包括但不限于从起点走到终点有多少种方案走法,洛谷P1605就是迷宫模板题(传送门:迷宫 - 洛谷)。按照DFS不撞南墙不回头的思路,这道题应该是信手捏来的吧。代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+5;
int ans=0,x_[5]={0,1,0,-1},y_[5]={1,0,-1,0};//x_[],y_[]模拟方向数组
int n,m,t,start_x,start_y,end_x,end_y;
int mp[20][20],vis[20][20];//mp地图,vis作为监视数组判断是否已经来过这个点
void dfs(int x,int y){
if(x==end_x&&y==end_y){//到了终点后方案数就++并且return
ans++;
return ;
}
for(int i=0;i<4;i++){
int dx=x+x_[i];
int dy=y+y_[i];
if(dx>=1&&dy>=1&&dx<=n&&dy<=m&&mp[dx][dy]==0&&!vis[dx][dy]){//这里老规矩 判断越界 vis判断没来过 mp[dx][dy]判断是否为障碍物
vis[dx][dy]=1;//该点没来过且不是障碍物 所以该点目前可行 标记此点已来过
dfs(dx,dy);//从这里回溯出来后说明该点无解 回溯vis[][]为0未标记过
vis[dx][dy]=0;
}
}
return ;
}
void solve(){
cin>>n>>m>>t>>start_x>>start_y>>end_x>>end_y;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]=0;//初始化全是0
}
}
for(int i=1;i<=t;i++){
int a,b;
cin>>a>>b;//对于障碍 设置为1
mp[a][b]=1;
}
vis[start_x][start_y]=1;//一定要有这句 你的起点肯定来过所以为1,不然方案数可能会变成答案的2倍(->->和->折回再->->);
dfs(start_x,start_y);
cout<<ans<<endl;
}
signed main(){
solve();
return 0;
}
于是写到这里对深搜的理解就好多了,正准备接着写洛谷题单时,发现这道1443感觉又像是迷宫了,不过没有障碍物了,走的方向也从4个变成了8个,第一反应换汤不换药依葫芦画瓢继续用DFS写,大不了用min()来维护最少次数吧。但问题是如果每次都一条路走到黑,这题有尽头吗?用深搜每个点可能不止考虑一次,所以用监视数组显然不行,怎么办呢?于是想到用BFS。
BFS广度优先搜索,就是地毯式搜索,可以理解为病毒扩散的样子:
(图很丑见谅)
他的搜索顺序便是
即3,4是一同搜索,5 6 7 8 9 10是一同搜索,可以理解为去学校厕所,厕所门全关了,DFS是敲门→开门→进去查看,而BFS是先全敲一次门,然后把所有门打开,全部一起查看(可能有点怪);但可以想想这个过程,所以DFS可以用stack栈或者递归来写,BFS就是用queue队列来写,对于这道题就要用BFS:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+5;
int x_[10]={1,1,-1,-1,2,2,-2,-2};//8个方向模拟的方向数组
int y_[10]={2,-2,2,-2,1,-1,1,-1};
int mp[500][500];
struct node{
int x,y,c;
};//用结构体x,y坐标和c最短次数
queue<node>que;//用队列存结构体写BFS
void solve(){
int n,m,start_x,start_y;//简单输入
cin>>n>>m>>start_x>>start_y;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]=-1;//初始化为-1,题目说了去不了的地就是-1,干脆就写-1了
}
}
mp[start_x][start_y]=0;//同样是初始化
que.push((node){start_x,start_y,0});//存进队列
while(!que.empty()){//这里就是BFS的模板
node f=que.front();
que.pop();
for(int i=0;i<8;i++){//八个方向
int dx=f.x+x_[i];//和DFS异曲同工
int dy=f.y+y_[i];
if(mp[dx][dy]==-1&&dx>=1&&dy>=1&&dx<=n&&dy<=m){//不同点在于在该点处可达的8个方向点
mp[dx][dy]=f.c+1;//如果为-1即没来过的点,那么最少次数一定是该点处次数+1,可以停下来理解理解
que.push((node){dx,dy,mp[dx][dy]});//存进队列
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%-5d",mp[i][j]);//简单输出
}
cout<<endl;
}
}
signed main(){
solve();
return 0;
}