递归、分治-Ackerman函数

之前学习过递归与回溯,现在学习一下递归与分治

分治的思想:对这k个子问题分别求解,如果子问题的规模仍然不够小,则再划分为多个规模更小的子问题,如此的递归进行下去,直到问题规模足够小,很容易求出其解为止。将求出的小规模问题的解,合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。

当一个函数及它的一个变量是由函数自身定义时,称这个函数是双递归函数

Ackerman函数A(n,m)有两个独立的整型变量 m >=0 和 n >=0 ,其定义如下:

A(1,0) = 2                       

A(0,m) = 1                                                       m>=0

A(n,0) = n+2                                                    n>=2

A(n,m) = A(A(n-1,m), m-1)                              n,m >= 1

A(n,m)的自变量m的每一个值都定义了一个单变量函数:

m=0时,A(n,0) = n+2   n>=2

m=1时,A(n,1) = A(A(n-1,1),0) = A(n-1,1) + 2,和 A(1,1) = 2,故A(n,1) = 2*n n>=1

m=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)=2n    n ≥1

m=3时,类似的可以推出 A(n,3)= 2^{2^{2^{...}}}其中2的层数为n

m=4时,A(n,4)的增长速度非常快,以至于没有适当的数学式子来表示这一函数。

递归实现:

unsigned int akm(unsigned int n, unsigned int m)
{
    if(n==1 && m==0)
        return 2;
    else if(n==0 && m>=0)
        return 1;
    else if(n>=2 && m==0)
        return n+2;
    else
        return akm(akm(n-1, m), m-1);
}

非递归形式(这份代码并不是很严谨,因为计算过程中可能会溢出,所以最好用上一份代码):

//非递归形式: 不严谨,有可能溢出。
int Ackerman(int n, int m)
{
    int i, j, akm[maxn][maxn];

    memset(akm, 0, sizeof(akm));   //一段内存设为0,用于空间初始化
    akm[1][0] = 2;

    for(i = 0; i < maxn; i++)
        akm[0][i] = 1;
    for(i = 2; i < maxn; i++)
        akm[i][0] = i + 2;
    for(j = 1; j < maxn; j++)
        for(i = 1; i < maxn; i++)
            akm[i][j] = akm[akm[i-1][j]][j-1];

    return akm[n][m];
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值