利用深度优先搜索解决水仙花数问题
题目描述:水仙花数是指一个N位正整数(N>=3),它的每个位上的数字的N次幂之和等于它本身。例 如:153 = 1^3 + 5^3+ 3^3。
本题要求编写程序,计算所有N位水仙花数。
输入格式:
输入在一行中给出一个正整数N(3<=N<=7)。
输出格式:
按递增顺序输出所有N位水仙花数,每个数字占一行。
输入样例:
3
输出样例:
153
370
371
407
算法分析:
本题是穷举法的典型应用。我们可以设置一个数组来存储每一位数字,然后采用深度优先搜索(类似穷举全排列的方法),组合出每一个n位数,然后判断其是否为水仙花数。我实现了递归和非递归两种算法,并对求幂的算法进行了优化。奇怪的是非递归算法竟然比递归算法还要慢,真是不得其解,还望大牛指点。
说明:
算法思想:穷举法,深度优先搜索
数据结构:数组。
时间复杂度: O(10^n);
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
int Num[10] = {0};
void dfs(int top, int n);//回溯法求水仙花数
int pow(int a, int n);//递归法求幂
void DaffodilNumber(int n);//穷举法求水仙花数(非递归)
int main(void)
{
clock_t start, finish;
double duration;
int i, n;
scanf("%d", &n);
start = clock();
for (i=1; i<10; i++) //回溯法求水仙花数,最高位不能为0
{
Num[0] = i;
dfs(1, n);
}
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "%f seconds\n", duration );
start = clock();
DaffodilNumber(n);//穷举法求水仙花数(非递归)
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "%f seconds\n", duration );
return 0;
}
void dfs(int top, int n)//回溯法求水仙花数
{
int i, s1, s2;
if (top == n)
{
s1 = s2 = 0;
for (i=0; i<n; i++)
{
s1 += pow(Num[i], n);
s2 = s2 * 10 + Num[i];
}
if (s1 == s2)
{
for (i=0; i<n; i++)
printf("%d", Num[i]);
printf("\n");
}
return ;
}
for (i=0; i<10; i++)
{
Num[top] = i;
dfs(top+1, n);
}
}
int pow(int a, int n)//递归法求幂
{
int s;
if (a == 0 || a == 1 || n == 1)
return a;
if (n == 0)
return 1;
s = pow(a, n/2);
return (n%2 == 0) ? (s * s) : (s * s * a);
}
void DaffodilNumber(int n)//穷举法求水仙花数(非递归)
{
int i, j, top, s1, s2;
for (i=1; i<10; i++)
{
Num[0] = i;
Num[1] = -1;
top = 1;
while (top > 0)
{
if (top == n)
{
s1 = s2 = 0;
for (j=0; j<n; j++)
{
s1 += pow(Num[j], n);
s2 = s2 * 10 + Num[j];
}
if (s1 == s2)
{
for (j=0; j<n; j++)
printf("%d", Num[j]);
printf("\n");
}
--top; //返回上一个数字
}
else if (Num[top] < 9)
{
Num[top++]++;
Num[top] = -1;
}
else
{
--top;
}
}
}
}






