先按照题意把递归的内容写出来,然后把每次0~20以内的答案记录下来,下一次递归时如果rpt(x,y,z)有记录就直接输出,能省去大量时间。
注意:输入中有负数,因此一开始的判断语句不能只写if(rpt[x][y][z]),因为不能访问数组负数下标,应加一个特判。
记忆化搜索:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll rpt[25][25][25];//全局变量数组自动置零
ll w(ll a, ll b, ll c)//用三维数组记录递归得到的值,减少递归次数
{
if (a <= 0 || b <= 0 || c <= 0) return 1;
else if (rpt[a][b][c] != 0)return rpt[a][b][c];//不能写在第一句,如果下标为负,数组会越界
//把数组初始化成不可能达到的值,判断条件就是不等于这个不可能达到的值
else if (a > 20 || b > 20 || c > 20)rpt[a][b][c] = w(20, 20, 20);
else if (a < b&&b < c)rpt[a][b][c] = w(a, b, c - 1) + w(a, b, c - 1) - w(a, b - 1, c);
else rpt[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 rpt[a][b][c];
}
int main()
{
ll a, b, c;
while (cin >> a >> b >> c)
{
if (a == -1 && b == -1 && c == -1)break;
cout << "w(" << a << ", " << b << ", " << c << ") = ";
if (a > 20)a = 21;if (b > 20)b = 21;if (c > 20)c = 21;//防止数组越界
cout << w(a, b, c) << endl;
}
return 0;
}