今天主要学习的是dfs,dfs,主要思想就是通过不断的探索,一条路一直往下走,直到无法再进行为止,主要的代码:
1.dfs典型问题:
洛谷P1605 迷宫
---------------------------------------------------------------------------------------------------------------------------------
题目描述
给定一个 N \times MN×M 方格的迷宫,迷宫里有 TT 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N,M,TN,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 SX,SY,FX,FYSX,SY,FX,FY,SX,SYSX,SY 代表起点坐标,FX,FYFX,FY 代表终点坐标。
接下来 TT 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
---------------------------------------------------------------------------------------------------------------------------------
题解:典型的dfs问题,将迷宫看做是一共二维数组,问题结束的条件就是从起始位置到达终止位置,由此可以得出判断条件
然后开始不断尝试不同的可能,根据上、下、左、右的位置不断改变,不断去尝试和标记,同时注意题目中给出了障碍物,所以尝试的条件除了不能超越迷宫本身的边界的同时还要避开障碍物,于是可以定义一个全局二维数组,在开始全体为0,将题目给出的障碍物标记为1,可以得到主要d代码:
然后根据题目给出的数据写主函数就行,同时还要注意:障碍物可能不止一个,要注意用循环。
完整代码:
#include <stdio.h>
int a[6][6];//地图
int b[6][6];//标记图
int n,m,t;
int sx,sy,fx,fy,zx,zy;
int cnt=0;
int next[4][2]= {{0,1}, //向右走
{1,0},//向下走
{0,-1},//向左走
{-1,0}//向上走
};
void dfs(int x,int y)
{
if(x==fx&&y==fy)//判断结束条件
{
cnt++;
return ;
}
int tx,ty;
for(int i=0; i<=3; i++)
{
tx=x+next[i][0];//下一步x的位置
ty=y+next[i][1];//下一步y的位置
if(tx<1||tx>n||ty<1||ty>m)//判断是否越界
continue;
if(a[tx][ty]==0&&b[tx][ty]==0)
{
b[tx][ty]=1;
dfs(tx,ty);
b[tx][ty]=0;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&t);
scanf("%d%d%d%d",&sx,&sy,&fx,&fy);
while(t--)
{
scanf("%d%d",&zx,&zy);
a[zx][zy]=1;//障碍物的标记
}
b[sx][sy]=1;
dfs(sx,sy);
printf("%d\n",cnt);
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------
2.P2404 自然数的拆分问题
---------------------------------------------------------------------------------------------------------------------------------
题目描述
任何一个大于 11 的自然数 nn,总可以拆分成若干个小于 nn 的自然数之和。现在给你一个自然数 nn,要求你求出 nn 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数 nn。
输出格式
输出:若干数的加法式子。
---------------------------------------------------------------------------------------------------------------------------------
题解:首先很容易得知:我们所写的式子的和加起来要与题目给出的值相同,所以要设定一个数来与题目给出的n判断可以得出结束条件:
同时我们要选数字不断增加,这里也要设定一个数,从哪一个数开始,同时注意开始的数不能与题目给出的数相同,相同就无法写出相加的式子,也可以得出一个判断条件:
然后就是最主要的尝试每一种可能的部分:设定一个数z,定义一个数组,以z为下标,然后去不断存放我们尝试可行的数,然后下一步的和要加上这一个步骤放进去的数:
然后根据题目要求的输出写一个输出函数和主函数就行。
#include <stdio.h>
int a[50];
int n;
void prin(int x)//输出函数
{
for(int i=0;i<x-1;i++)
{
printf("%d+",a[i]);
}
printf("%d",a[x-1]);
printf("\n");
return ;
}
void dfs(int x,int y,int z)
{
if(x==n)//开始相加的数不能与题目的数相等
return ;
if(y==n)//相加式子的和要与题目的数相等
{
prin(z);
return ;
}
for(int i=x;i<=n-y;i++)
{
a[z]=i;
dfs(i,y+i,z+1);
}
}
int main()
{
scanf("%d",&n);
dfs(1,0,0);
return 0;
}