深度优先搜素(Depth First Search,DFS),DFS的关键在于解决“当下该如何做”。至于“下一步如何做”与“当下如何做”是一样的,比如我们这里写的dfs(step)函数的主要功能是解决当你在第step个盒子的时候你该怎么办。通常的办法就是把每一种可能都去尝试一遍(一般使用for循环来遍历)。当前这一步解决后便进入下一步dfs(step+1)。下一步的解决方法和当前这步的解决方法是完全一样的。下面的代码就是深度优先搜素的基本模型。
void dfs(int step)
{
判断边界
尝试每一种可能 for(i=1;i<=n;i++)
{
继续下一步 dfs(step+1);
}
返回
}
不撞南墙不回头——深度优先搜素
输入一个数n,输出1~n的全排列
例如有编号为1、2、3的3张扑克牌和编号为1、2、3的3个盒子/现在需要将这3张扑克牌分别放到这3个盒子里,并且每个盒子有且只能放一张扑克牌,那么一共有多少种放法呢
小哼约定了一个顺序:每次到一个盒子面前时,都先放1号,再放2号,最后放三号扑克牌
//这里数组a表示小盒子,变量step表示当前正处在第step个小盒子面前
//a[step]=i;就是将第i号扑克牌放入到第step个盒子里,数组book用来标记哪些牌已经使用了
#include<stdio.h>
int a[10],book[10],n;//c语言的全局变量在没有赋值以前默认为0
int main()
{
void dfs(int step);
scanf("%d",&n);
dfs(1);//首先站在1号小盒子面前
return 0;
}
void dfs(int step)
{
int i;
if(step==n+1)//如果站在第n+1个盒子前,则表示前n个盒子已经放好扑克牌了
{
//输出一种排序(1~n盒子中的扑克牌编号)
for(i=1;i<=n;i++){
printf("%d ",a[i]);
}
printf("\n");
return ;//返回之前的一步(最近调用dfs函数的地方)
}
//此时站在第step个盒子面前,应该放哪张牌呢?
//按照1、2、3...n的顺序一一尝试
for(i=1;i<=n;i++){
//判断扑克牌i是否还在手上
if(book[i]==0){//book[i]=0表示i号扑克牌在手上
//开始使用扑克牌i
a[step]=i;//将i号扑克牌放入第step个小盒子中
book[i]=1;//i号扑克牌已经不在手中
//第step个盒子已经放好扑克牌,接下来走到下一个盒子里
dfs(step+1);//递归调用
book[i]=0;//一定要将刚才尝试的扑克牌收回,才能进行下一次尝试
}
}
return ;
}
坑爹的奥数——枚举/DFS
【】【】【】+【】【】【】=【】【】【】
将数字1~9分别填入9个【】中,每个数字只能使用一次使得等式成立
枚举
#include<stdio.h>
int main()
{
int a[10],i,total=0,book[10],sum;
for(a[1]=1;a[1]<=9;a[1]++)
for(a[2]=1;a[2]<=9;a[2]++)
for(a[3]=1;a[3]<=9;a[3]++)
for(a[4]=1;a[4]<=9;a[4]++)
for(a[5]=1;a[5]<=9;a[5]++)
for(a[6]=1;a[6]<=9;a[6]++)
for(a[7]=1;a[7]<=9;a[7]++)
for(a[8]=1;a[8]<=9;a[8]++)
for(a[9]=1;a[9]<=9;a[9]++){
for(i=1;i<=9;i++)//初始化book数组
book[i]=0;
for(i=1;i<=9;i++)//如果某个数出现过就标记一下
book[a[i]]=1;
//统计共出现了多少个不同的数
sum=0;
for(i=1;i<=9;i++)
sum+=book[i];
//如果正好出现了9个不同的数,并且满足等式条件,则输出
if(sum==9&&a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9])
{
total++;
printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
}
}
printf("total=%d",total/2);
return 0;
DFS
//相当于手中有编号为1~9的九张扑克牌,然后将这九张扑克牌放到九个盒子中
#include<stdio.h>
int a[10],book[10],total=0;
int main()
{
void dfs(int step);
dfs(1);//首先站在一个盒子前
printf("total=%d",total/2);
return 0;
}
void dfs(int step)
{
int i;
if(step==10)//如果站在第10个盒子面前,则表示前9个盒子已经放好扑克牌
{
//判断是否满足等式
if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9])
{
//如果满足要求,加一,并打印这个解
total++;
printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
}
return ;//返回之前的一步
}
//此时站在第step个盒子面前,应该放哪张牌呢?
//按照1、2、3...n的顺序一一尝试
for(i=1;i<=9;i++){
//判读扑克牌i是否还在手上
if(book[i]==0)
{
a[step]=i;
book[i]=1;
dfs(step+1);
book[i]=0;
}
}
return ;
}