主题:求解阿克曼函数问题.急!!!!!!
joky
[专家分:120] 发布于 2006-06-01 12:31:00
定义阿克曼递归函数:
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个回复)
沙发
rickone [专家分:15390] 发布于 2006-06-01 14:14:00
给我一个计算范围,才好确定存储范围.这样函数是递归定义的,又没要你用递归写程序.
板凳
joky [专家分:120] 发布于 2006-06-01 15:59:00
不好意思,让各位久等了,我刚下课.
好的,它的计算范围就是能输入m能输入10以上吧.谢谢.
3 楼
zyxdna [专家分:1250] 发布于 2006-06-01 18:09:00
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 楼
joky [专家分:120] 发布于 2006-06-01 18:29:00
这是我写的程序,跟你写的也没什么差别.结果也是输不出(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 楼
zouyu1983 [专家分:1670] 发布于 2006-06-02 09:48:00
#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 楼
zouyu1983 [专家分:1670] 发布于 2006-06-02 09:49:00
A函数增长速度是惊人的,用递归分治是不可能解决的,动态规划可以
可以分析A函数的规律,改为直接求解,oj上就有一题类似的
首先,递归深度太深,可能导致堆栈溢出,复杂度太大,可能导致tls, 反正,肯定过不了OJ的测试
7 楼
joky [专家分:120] 发布于 2006-06-02 20:45:00
是呀,由于它的增长速度太快,用递归是很容易溢出的,不过如果改变默认的堆栈大小的话就能计算出m=4,n=1,不过都要等很久才能看到结果.以前听说有人自己写堆栈实现了m=5,n=7,真是强,
8 楼
rickone [专家分:15390] 发布于 2006-06-02 23:30:00
不好意思,我一开始看错了,6楼说DP可以求?不知道具体算法如何.7楼,自己写栈不能从时间上省下来,同样要等好久(太久甚至就是不可能)
9 楼
joky [专家分:120] 发布于 2006-06-03 00:14:00
呵呵,也是,不过至少那样可以自己控件堆栈的大小,而不用去更改默认的堆栈大小,那你有什么好的算法吗?
10 楼
xfcyjhb [专家分:0] 发布于 2007-12-11 16:13:00
虽然计算机不能求出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)就知道有多大了, 而阿克曼函数又是递归函数,每算一个阿克曼数就需要把前面的每一个数算一遍,可见算的次数有多少了
我来回复