回 帖 发 新 帖 刷新版面

主题:求解阿克曼函数问题.急!!!!!!

定义阿克曼递归函数:
ACK(0,n)=n+1         n>=0
ACK(m,0)=ACK(m-1,1)        m>=1
ACK(m,n)=ACK(m-1,ACK(m,n-1))      m,n>0 

当输入m=3,n=11(或n>11)或m=4(或m>4),n=1(或n>1)时就不能输出计算结果, 就会溢出,请问各位高手,怎么解决这个溢出问题呀?

回复列表 (共10个回复)

沙发

给我一个计算范围,才好确定存储范围.这样函数是递归定义的,又没要你用递归写程序.

板凳


不好意思,让各位久等了,我刚下课.
好的,它的计算范围就是能输入m能输入10以上吧.谢谢.

3 楼

ACK(0,n)=n+1         n>=0
ACK(m,0)=ACK(m-1,1)        m>=1
ACK(m,n)=ACK(m-1,ACK(m,n-1))      m,n>0

ACK(0,0)=1,ACK(0,1)=2,ACK(0,2)=3,ACK(0,3)=4,ACK(0,4)=5,ACK(0,5)=6
ACK(1,0)=2,ACK(1,1)=3,ACK(1,2)=4,ACK(1,3)=5,ACK(1,4)=6,ACK(1,5)=7
在m=3,n=11应该还不至于溢出的
#include<stdio.h>
int ack(int m,int n)
{
     int num;
     if(m==0)
         return n+1;
     if(m>0&&n==0)
     {
         num=ack(m-1,1);
         return num;
     }
     if(m>0&&n>0)
     {
          num=ack(m-1,ack(m,n-1));
          return num;
     }
}
main()
{
     int m,n,c;
     scanf("%d,%d",&m,&n);
     printf("ack(%d,%d)=",m,n);
     printf("%d\n",ack(m,n));
     while(1);
}

ack(3,11)=16381
ack(3,12)=ack(2,16381)=32765
后面的就不敢保证了


4 楼

这是我写的程序,跟你写的也没什么差别.结果也是输不出(3,11)的结果,我调试了你的程序,也是输不出结果来,已经溢出.
如果改变VC6.0中默认的stack size大小的话就能输出,不过这不是我们所想要的.
#include<iostream.h>
long int count=0;

long int ACK(int m, int n) 

    long int temp; 
    count++;
    if (m == 0)  
        return (n + 1); 
    else if (n == 0)  
        return ACK(m - 1, 1); 
    else
    { 
        temp = ACK(m, n - 1); 
        return ACK(m - 1, temp); 
    } 
}

int main(int argc, char* argv[])
{
    int m,n;
    cin>>m>>n;
    cout<<ACK(m,n)<<endl;
    cout<<"共调用 "<<count<<" 次!"<<endl;
    return 0;
}

5 楼

#include <stdio.h>

int main()
{
    int value[25];
    int i,m,n;
    value[0] = 5;
    
    for (i=1; i<25; i++)
    {
        value[i] = value[i - 1] * 2 + 3;
    }
    
    while (scanf("%d%d", &m, &n) != EOF)
    {
        switch(m)
        {
        case 0: printf("%d\n", n + 1);
                break;
        case 1: printf("%d\n", n + 2);
                break;
        case 2: printf("%d\n", 3 + 2 * n);
                break;
        case 3: printf("%d\n", value[n]);
                break;
        default:break;
        }
    }
    return 0;
}


此程序通过FZU OJ的测试,仅供参考

6 楼

A函数增长速度是惊人的,用递归分治是不可能解决的,动态规划可以

可以分析A函数的规律,改为直接求解,oj上就有一题类似的

首先,递归深度太深,可能导致堆栈溢出,复杂度太大,可能导致tls, 反正,肯定过不了OJ的测试

7 楼


是呀,由于它的增长速度太快,用递归是很容易溢出的,不过如果改变默认的堆栈大小的话就能计算出m=4,n=1,不过都要等很久才能看到结果.以前听说有人自己写堆栈实现了m=5,n=7,真是强,

8 楼

不好意思,我一开始看错了,6楼说DP可以求?不知道具体算法如何.7楼,自己写栈不能从时间上省下来,同样要等好久(太久甚至就是不可能)

9 楼


呵呵,也是,不过至少那样可以自己控件堆栈的大小,而不用去更改默认的堆栈大小,那你有什么好的算法吗?

10 楼


虽然计算机不能求出A(3,10) A(3,11)以及以后的阿克曼函数,但是我已经求出了A(3,n) A(2,n), A(1,n)的数学通项
A(1,n)=n+2
A(2,n)=2n+3
A(3,n)=2的(n+3)次方 减3
而A(4,1)=2的16次方 减3
A(4,2)=2的(2的16次方) 减3
A(4,3)=2的[2的(2的16次方)] 减3
而A(4,n)就是2的2的2的...(n个2)16次方 减3
算一下A(4,2)就知道有多大了, 而阿克曼函数又是递归函数,每算一个阿克曼数就需要把前面的每一个数算一遍,可见算的次数有多少了

我来回复

您尚未登录,请登录后再回复。点此登录或注册