题目描述
对于一个递归函数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)。
题解
经典记忆化搜索,因为有重复计算,所以每次把计算结果保存下来。
#include <iostream>
using namespace std;
#define ll long long
ll f[30][30][30];
int w(ll a, ll b, ll c){
if(a<=0 || b<=0 || c<=0) return 1;
else if(a>20 || b>20 || c>20) return w(20,20,20); //保证接下来不会超过20
else if (f[a][b][c] != 0) return f[a][b][c];
else if(a<b && b<c) f[a][b][c] = w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else f[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 f[a][b][c];
}
int main(){
ll a, b, c;
while(1){
scanf("%lld%lld%lld", &a, &b, &c);
if(a==-1 && b==-1 && c ==-1) break;
printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, w(a,b,c));
}
return 0;
}
注意点:
由于可能a、b、c为负数,所以判断a<=0 || b<=0 || c<=0
直接返回1,加之a>20 || b>20 || c>20
直接返回w(20,20,20)的条件,可知f[][][]数组下标不会超过20。因此数组下表只需要都大于20就可以啦!