1、什么是深搜?
深度优先搜索属于图算法的一种,英文缩写为DFS,即 Depth First Search。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了,回溯到A),A->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束)。
2、深搜框架
void backtrack(int t)
{
if ( t>n) // t:递归深度,即当前扩展结点在解空间树中的深度,t>n,搜索至叶子结点
output(x) // 记录或输出可行解
else
for i=start to end // strat,end,当前扩展点处未搜索过的子树的起始编号和终止编号
{
x[t]=h(i) // h(i):当前扩展点处x[t]的第 i 个可选值
if (当前扩展结点的约束条件)
backtrack(t+1)
}
}
3、从枚举到深搜
一个三位数abc,如果满足abc = a^3+ b^3+ c^3,那么就把这个数叫做水仙花数。如果一个N位数所有数码的N次方的和加起来等于这个数字本身,我们把这样的数叫做广义水仙花数,现在,我们的任务是,输入一个m (m<7),让你求出所有满足N = m的广义水仙花数。
样例输入1:3 样例输出2:153 370 371 407
样例输入2:5 样例输出:54748 92727 93084
分析:
如果是水仙花问题,可以用枚举,直接求出。代码如下:
#include <stdio.h>
int main()
{
int i,a,b,c;
for(i=100;i<=999;i++)
{
a=i/100;
b=i/10%10;
c=i%10;
if(a*a*a+b*b*b+c*c*c==i)
printf("%d ",i);
}
printf("\n");
return 0;
}
或:
#include <stdio.h>
int main()
{
int a,b,c;
for(a=1;a<=9;a++)
for(b=0;b<=9;b++)
for(c=0;c<=9;c++)
if(a*a*a+b*b*b+c*c*c==a*100+b*10+c)
printf("%d%d%d ",a,b,c);
printf("\n");
return 0;
}
现在求广义的水仙花,现在的难点是不知道是几位数?也不知道是几次方?循环层数不确定,那么该如何实现m重循环?答案只有一个:就是递归,让系统自动调用函数,自动实现循环。
套用上面深搜(回溯)模板,代码自然而成。
#include <stdio.h>
#include <math.h>
int n;
void flower(int t,int curNum,int curSum)
{
int i,start;
if(t>n)
{
if(curNum==curSum)
printf("%d ",curNum);
}
else
{
start=(t==1); // 第一位不为0,第一位1~9枚举,其他位0~9枚举
for(i=start;i<=9;i++)
flower(t+1,curNum*10+i,curSum+(int)pow(i,n));
// 缩小问题规模
}
}
int main()
{
while(scanf("%d",&n) && n)
{
flower(1,0,0);
printf("\n");
}
return 0;
}