讲深搜的话,拿经典的迷宫问题来说明是最好的,刚好最近在洛谷上刷到了一道迷宫题,就以它为例了,原题在下面
P1605 迷宫
题目要求
输入输出格式
输入输出样例
输入样例:
2 2 1
1 1 2 2
1 2
输出样例:
1
【数据规模】
1≤N,M≤5
题目整体来说比较简单,思路就是使用深搜一个一个查,用两个数组分别标记走过的点和障碍物,使用自动选择方向来简化代码,没有遇到障碍物并且不是自己走过的就进一步搜索,把自己走过的路打上标记,返回时,再将标记还原。
具体细节在代码里注释有,下面放上我的AC代码:
#include<bits/stdc++.h> //万能头文件
using namespace std;
int maps[10][10]; //标记迷宫障碍
int visit[10][10]; //标记已经访问过的点
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //上下左右四种移动方式(根据题目不同可改变,有的题目是两种移动方式,用二维数组即可)
int sx,sy,fx,fy; //起点和终点的坐标
int N,M; //N行M列
int num=0; //记录方案数
//深搜
void dfs(int x,int y) //横坐标和竖坐标
{
if(x==fx&&y==fy) //到达终点了
{
num++;
return;
}
else{
for(int i=0;i<4;i++){
//记录新的坐标
int a=x+d[i][0];
int b=y+d[i][1];
if(a<1||a>N||b<1||b>M) //越界处理
continue;
if(visit[a][b]==1) //避免重复
continue;
if(maps[a][b]==1) //碰到障碍物了
continue;
visit[a][b]=1; //标记走过的点
dfs(a,b);
visit[a][b]=0; //回溯(这步很重要,恢复原来的标记)
}
}
}
int main(){
int T,l,r; //障碍物总数和坐标
//初始化
memset(maps,0,sizeof(maps));
memset(visit,0,sizeof(visit));
cin>>N>>M>>T;
cin>>sx>>sy>>fx>>fy;
for(int i=0;i<T;i++){
cin>>l>>r;
maps[l][r]=1; //为障碍物打上标记
}
visit[sx][sy]=1; //为起点打访问标记
dfs(sx,sy);
cout<<num;
return 0;
}
这里再给大家一个基本的深搜模板:
int search(int t)
{
if(满足输出条件)
{
输出解;
}
else
{
for(int i=1;i<=尝试方法数;i++)
if(满足进一步搜索条件)
{
为进一步搜索所需要的状态打上标记;
search(t+1);
恢复到打标记前的状态;//也就是说的{回溯一步}
}
}
}
整个模板有几个地方需要注意:
1.第一个if是符合输出解的条件,第二个if是符合进一步搜索的条件;
2.下一步搜索时,不是使用return search(t+1),直接search(t+1);(新手可能会注意不到这个关键的地方,以至于每次写完不知道为什么只得到一个答案就返回主程序了)
3.for循环之后的if可以是多个;
4.for循环边界,例如:
1>方向是四个,那么边界肯定就是4;(下面有两个方向的例题)
2>素数环需要尝试1至20,那么边界就是20;(素数环也是一种运用深搜的经典题,具体百度)
来说下上面提到的两个方向的情况,基本上是照葫芦画瓢,拿一个最近在牛客月赛上做的题来说明
小雨的矩阵(原题点这里)
题目要求有点不同,但是运用上面的深搜模板来做同样可以很快地AC了
大家可以尝试做一下再看我的代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int c[10][10];
int way[2][2]={{1,0},{0,1}};
set<int> s; //set容器,自动删除插入的重复元素
void dfs(int x,int y,int ans){
ans+=c[x][y];
if(x==n && y==n){
s.insert(ans);
return;
}
for(int i=0;i<2;i++){
int a=x+way[i][0];
int b=y+way[i][1];
if(a>n || b>n) //不可能出现往回走的情况
continue;
dfs(a,b,ans);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>c[i][j];
dfs(1,1,0);
cout<<s.size()<<endl; //返回容器中的元素个数,自动去重
return 0;
}
从(1,1)爆搜到(n,n),把答案去一下重即可,用到模板了是不是很简单
如果想要得到更多知识,请关注我博客:wlis.blog.csdn.net
此博客不定期更新内容!!!感谢大家!!!