DFS是一种经典的搜索算法,也是检测有没有编程天赋的试金石。
DFS:搜索与回溯
题1:自然数的拆分
cpp
//自然数的拆分
#include<bits/stdc++.h>
using namespace std;
int n,ans[101];
void dfs(int sum,int dp){
if(sum>n){
return;//不可以让若干个数的和大于n
}
if(sum==n){
for(int i=1;i<=dp-2;i++){
printf("%d+",ans[i]);
}
printf("%d\n",ans[dp-1]);
}
for(int i=ans[dp-1];i<n;i++){//是组合而不是全排列
ans[dp]=i;
dfs(sum+i,dp+1);
}
}
int main(){
scanf("%d",&n);
ans[0]=1;//从1开始
dfs(0,1);
}
迷宫问题:(洛谷)
迷宫
题目描述
给定一个 N \*M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标,FX,FY 代表终点坐标。
接下来 T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
样例 #1
样例输入 #1
```
2 2 1
1 1 2 2
1 2
```
样例输出 #1
```
1
```
提示
对于 100\\% 的数据,1 \\le N,M \\le 5,1 \\le T \\le 10,1 \\le SX,FX \\le n,1 \\le SY,FY \\le m。
code:
cpp
#include<bits/stdc++.h>
using namespace std;
int q[101][101];
int sum=0;
int i,j,n,m,t,sx,sy,x,y,ex,ey;
void dfs(int a,int b)
{
if (a==ex&&b==ey){//终止条件
sum++;
return;
}
else
{
q[a][b]=0;
if(q[a-1][b]!=0) {dfs(a-1,b);q[a-1][b]=1;}
if(q[a][b-1]!=0) {dfs(a,b-1);q[a][b-1]=1;}
if(q[a][b+1]!=0) {dfs(a,b+1);q[a][b+1]=1;}
if(q[a+1][b]!=0) {dfs(a+1,b);q[a+1][b]=1;}
}
}
int main()
{
memset(q,0,sizeof(q));//边界当作障碍。
cin>>n>>m>>t;
cin>>sx>>sy>>ex>>ey;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
q[i][j]=1;//可以走
for(i=1;i<=t;i++)
{
cin>>x>>y;
q[x][y]=0;//障碍物初始化
}
dfs(sx,sy);
cout<<sum<<endl;
return 0;
}
总结:
dfs模板:
cpp
int search(int t)
{
if(满足输出条件)
{
输出解;
}
else
{
for(int i=1;i<=尝试方法数;i++)
if(满足进一步搜索条件)
{
为进一步搜索所需要的状态打上标记;
search(t+1);
恢复到打标记前的状态;//也就是说的{回溯一步}
}
}
}