Function Run Fun [ZOJ – 1168]解读
题目:
https://zoj.pintia.cn/problem-sets/91827364500/problems/91827364667
题目给出接受三个参数的函数递归式
if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1 if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20) if a < b and b < c, then w(a, b, c) returns: w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c) otherwise it returns: w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
如果直接写成递归式肯定会超时,就像 ackerman (n,m)函数,收敛非常慢。就是因为计算的时候做了非常多的重复计算,所以可以把已经算过的数值保存下来,开一个数组,初始值为w()函数取不到的值,若算出来就更新其值,用到的时候就直接读取,会减少很多计算的时间从而顺利解决。有初步的动规思想
#include <cstdio> #include <cstring> int w[21][21][21]; int fw(int a,int b,int c) { if( a<=0 || b<=0 || c<=0) return 1; if ( a>20 || b>20 || c>20 ) return fw(20,20,20); if(w[a][b][c]>0) return w[a][b][c]; else { if ( a<b && b<c ) { w[a][b][c]=fw(a,b,c-1)+fw(a,b-1,c-1)-fw(a,b-1,c); return w[a][b][c]; } else { w[a][b][c] = fw(a-1,b,c)+fw(a-1,b-1,c)+fw(a-1,b,c-1)-fw(a-1,b-1,c-1); return w[a][b][c]; } } } void init() { memset(w,0,sizeof(int)*21*21*21); int a,b,c,i; for(i=0;i<=20;i++) { w[0][0][i]=1; w[0][i][0]=1; w[i][0][0]=1; w[i][i][0]=1; w[i][0][i]=1; w[0][i][i]=1; } } int main(void) { int a,b,c; init(); while(1) { scanf("%d%d%d",&a,&b,&c); if(a==-1 && b==-1 && c==-1) break; printf("w(%d, %d, %d) = ",a,b,c); printf("%d\n",fw(a,b,c) ); } return 0; }