我们经常会做一些递归的题型,在数据规模较小的情况下,不断的调用是可以的但是当数据规模太大时就会出现mte,wa等问题。例如经典例题Function。
-
- 1.6K通过
- 5K提交
- 题目提供者JosephZheng
- 标签云端评测
- 难度普及-
最新讨论
题目描述
对于一个递归函数w(a,b,c)
如果a<=0 or b<=0 or c<=0就返回值1.
如果a>20 or b>20 or c>20就返回w(20,20,20)
如果a<b并且b<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)
其它别的情况就返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)
这是个简单的递归函数,但实现起来可能会有些问题。当a,b,c均为15时,调用的次数将非常的多。你要想个办法才行.
/*
absi2011 : 比如 w(30,-1,0)既满足条件1又满足条件2
这种时候我们就按最上面的条件来算
所以答案为1
*/
输入输出格式
输入格式:
会有若干行.
并以-1,-1,-1结束.
保证输入的数在-9223372036854775808~9223372036854775807之间
并且是整数
输出格式:
输出若干行
格式:
[b]w(a,_b,c)=_你的输出(_代表空格)[/b]
输入输出样例
1 1 1
2 2 2
-1 -1 -1
w(1, 1, 1) = 2
w(2, 2, 2) = 4
说明
记忆化搜索
没错一道特别水的题但是却是记忆化搜索的本质所在。
首先分析题:叽里咕噜叽里咕噜…………………………
定义一个数组book[21][21][21]作为记忆化中储存搜索的,避免再一次算而导致时间,空间上的不足。然后就按照题意来写递归函数。特别注意if语句中的条件。首先是a,b,c的取值范围超过怎么样处理。然后第三个如果记忆数组等于零。也就是说记忆数组并没有被计算到,那么就要直接递归计算。这三个if都没实现就是记忆数组不为零,也就是说当计算到这一步的时候,此次递归被计算过一次。所以说直接返回计算结果。减少再次计算的时间和空间。有许多人会说一个问题:我感觉在写代码的时候,这一个数组应该放在一个等号的右面。就像说i=book[a][b][c]然后用i来进行计算。其实不是这样的,因为在第三个if中说如果记忆数组为零。那么就会进行递归计算。简单的说就是在一开始的时候必须要经过第三个if进行递归计算。。具体的实现过程就看代码吧。注意细节找找第二份代码的错误。
#include<iostream>
int book[21][21][21];
int w(int a,int b,int c)
{
if(a<=0||b<=0||c<=0)
return 1;
if(a>20||b>20||c>20)
return w(20,20,20);
if(!book[a][b][c])
{
if(a<b&&b<c)
book[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else
book[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
return book[a][b][c];
}
int main(){
int a,b,c;
while(1){
cin>>a>>b>>c;
if(a==-1&&b==-1&&c==-1) break;
cout<<"w( "<<a<<", "<<b<<", "<<c<<") = "<<w(a,b,c)<<endl;
}
return 0;
}
码2:
#include<iostream> #include<cstdio> using namespace std; int w(int,int,int); int w1[21][21][21]; int a,b,c; int main() { while(1){ cin>>a>>b>>c; if(a==-1&&b==-1&&c==-1) break; printf("w(%d, %d, %d) = %d ",a,b,c,w(a,b,c)); } return 0; } int w(int x,int y,int z) { if(x<=0 || y<=0 || z<=0) return 1; if(x>20 || y>20 || z>20) return w(20,20,20); if(!w1[x][y][z]) { if(x<y && y<z) { w1[x][y][z]=w(x,y,z-1)+w(x,y-1,z-1)-w(x,y-1,z); } else { w1[x][y][z]=w(x-1,y,z)+w(x-1,y-1,z)+w(x-1,y,z-1)-w(x-1,y-1,c-1); } } return w1[x][y][z]; }
这份代码写了之过了大约10遍,就过了一个数据点。(ps:在数据特别弱的题库做的)第一、第四说是mtl。
第二、第五说是wa。调了大约一小时。找到结果了:那就是,
倒数5行。-w(x-1……c-1)打错了,应该打成-w(x-1……z-1)。T_T哎。后悔当时写的时候太匆忙了!!!!!!!!!!!!
哎,注意细节!!!
(我的语言表达能力有限-_-!!!)