記憶化搜索的思路:
記憶化搜索就是我們記錄一下每一個狀態的值,比如說在這個題目中我們算出了 $ w(x,y,z) $ 那么我們就用一個數組 $ f[x][y][z] $ 來記錄這個函數在參數為 $ x,y,z $ 的時候的值,這樣我們下次遞歸到這里的時候我們直需要調用這個值而無需遞歸下去求解。
而且由於這個地方的我們可以發現只需要需要 $ f[i][j][k],0 \le i \le 20.0 \le j \le 20,0 \le k \le 20 $ 的值就可以了
需要注意的地方:
在進行記憶化搜索的時候,一定要注意下標越界的問題,並且我們在記憶化搜索的時候一定要注意把遞歸到的值存入數組。比如說今天就忘了存。還有我們要考慮那些只需要存比如說當 $ f[i][j][k] $ 中的 $ i $ 大於 $ 20 $ 的時候我們就沒有必要存了。
代碼:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long a,b,c;
long long f[50][50][50];
long long fuc(long long x,long long y,long long z)
{
if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
if(f[x][y][z]!=0) return f[x][y][z]; //記憶化搜索的重要地方
if(x<=0 || y<=0 || z<=0){
if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
return f[x][y][z]=1;
else return 1;
}
else if(x>20 || y>20 ||z>20)
return f[20][20][20]=fuc(20,20,20);
else if(a<b && b<c){
if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
return f[x][y][z]=fuc(x,y,z-1)+fuc(x,y-1,z-1)-fuc(x,y-1,z);
else return fuc(x,y,z-1)+fuc(x,y-1,z-1)-fuc(x,y-1,z);
}
else if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
return f[x][y][z]=fuc(x-1,y,z)+fuc(x-1,y-1,z)+fuc(x-1,y,z-1)-fuc(x-1,y-1,z-1);
else return fuc(x-1,y,z)+fuc(x-1,y-1,z)+fuc(x-1,y,z-1)-fuc(x-1,y-1,z-1);
}
int main()
{
while(true){
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,fuc(a,b,c));
}
return 0;
}
