|
函数在其函数体里又包含对其自身的调用,称为递归。例如阶乘函数f(n)就可以用递归表示为
int f(int n){
if(n==0){
return 1;
}
else{
return n*f(n-1)
}
}
而其非递归表示为
int g(int n){
int s=1;
if(n==0){
return 1;
}
else{
for(int i=1;i<=n,i++){
s=s*i;
}
return s;
}
}
可见非递归表示要复杂一些,对于更为复杂的问题,则更是如此,如以下所述的汉诺塔问题。
传说在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭。其实,如果每秒移动一块金片,移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。我们现在通过输入金片数m(如m=3),希望得到解决方案,三根柱子分别用A,B,C表示,其中A是原柱,C是目标柱,B是辅助柱。递归实现:
void hanoi(int n ,char x,char y,char z){
if(n==1){
cout<"<"<>m;
hanoi(m,'A','B','C');
}
非递归实现(主函数与递归实现相同,这里略去)
DEFINE MAXSTACK 100;
struct{
int n,returnadd;
char x,y,z;
}H;
struct{
int top;
H item[MAXSTACK];
}HStack;
void commonhanoi(int n,char A,char B,char C){
HStack s;
H cur;
int i;
IniStack(s);//初始化栈的函数具体实现略,以下进栈、出栈、GetTop、swap函数也同样;
cur.n=n;
cur.x=A;
cur.y=B;
cur.z=C;
cur.returnadd=1;
push(s,cur);
start:
cur=GetTop(s);
if(cur.n==1){
cout<"<"<
可见非递归实现要复杂得多,而且我们还省略了一系列函数的具体实现。
汉诺塔问题是一个NP(nondeterministic polynomial-time,非确定型多项式时间)问题。确定型机器是指,根据其某时刻执行的指令,可以确定其接下来执行的指令,而非确定型机器——这一模型——对下一步是有选择的,如果这些后面的指令中有一条通向正确的解,那么它将总是选择这一正确的步骤。NP完全问题是NP问题的一个子集,定义是,任意NP问题A的任何实例,都可以经(多项式)变换为某一NP完全问题B的一个实例,可以通过求解B然后将答案映射回原始的解答来求解A。
旅行推销员问题是一个NP(nondeterministic polynomial-time,非确定型多项式时间)完全问题,
阿德勒曼利用DNA计算解决“旅行推销员”问题——为一个在N个城市间奔忙的推销员找到一条最优路线——使之每个城市都能到,但又不能超过一次——的步骤是:
为每一个城市创建一个小号码的DNA链;
用多聚酶链式反应(PCR)对这些DNA链进行许多次复制;
把上一步复制所得的所有DNA链放入一支试管,由于DNA连接酶的作用,这些DNA链会随机组合连接为许多条长链;
利用胞质基因“消灭”那些首尾两部分不是开头和结束两个城市的链,然后运用PCR对剩下的链进行复制;
利用酶反应消除路式中包含的城市超过N的DNA链;
利用酶反应消除路式中不包含第一个城市的DNA链,然后对第二个到第N个城市重复这一操作;
此时剩下的链就是正确答案,运用PCR技术对其进行复制,运用电泳技术“解读”正确链中的DNA顺序,其结果就是各城市的正确排序。
这一思想与遗传算法是异曲同工的。所谓遗传算法(genetic algorithm)是指如下过程:
1.开始时随机生成一组字符串(或一组程序);
2.利用这些程序进行计算,筛选出其中效用最优者;
3.将效用最优者进行配对,代代“繁衍”,直到数量达到最大(maxsize);
4.返回步骤2,重复执行。
八皇后问题是指,在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。递归实现如下:
#include
using namespace std;
/*说明数组Octqueen[8],Octqueen[i]表示第i行皇后要摆放的列位置,m表示方案数(正确答案为m=92)*/
static int OctQueen[8] = { 0 }, m = 0;
bool check(int x, int y){
/*检查是否存在有多个皇后在同一行或同一“/”对角线或同一“\”对角线的情况,x和y分别表示行和列*/
for (int i = 0; i < x; i++){
int j = OctQueen[i];
if ((y == j)||((i + j) == (x + y))||((i - j) == (x - y))){
return false;
}
}
return true;
}
void count(int i){
int x;
for (x = 0; x < 8; x++)
{
if (check(i, x))
{
OctQueen[i] = x;
if (i==7){
m++;
OctQueen[i] = 0;
return;
}
count(i + 1);
OctQueen[i] = 0;
}
}
}
int main(int argc, char*argv[]){
count(0);
cout << m << endl;
system("pause");
return 0;
}
|