1. 程式人生 > 實用技巧 >P1464 Function(記憶化搜尋)

P1464 Function(記憶化搜尋)

題目描述

對於一個遞迴函式w(a,b,c)w(a,b,c)

  • 如果a0orb0orc0就返回值1.
  • 如果a>20orb>20orc>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]之間,並且是整數。

輸出格式

輸出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

輸入輸出樣例

輸入 #1
1 1 1
2 2 2
-1 -1 -1
輸出 #1
w(1, 1, 1) = 2
w(2, 2, 2) = 4

說明/提示

記憶化搜尋:(抄的百度)一般說來,動態規劃總要遍歷所有的狀態,而搜尋可以排除一些無效狀態。更重要的是搜尋還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。記憶化演算法在求解的時候還是按著自頂向下的順序,但是每求解一個狀態,就將它的解儲存下來,以後再次遇到這個狀態的時候,就不必重新求解了。這種方法綜合了搜尋和動態規劃兩方面的優點,因而還是很有實用價值的。

```cpp

#include<bits/stdc++.h>
using namespace std;
#define N 22
typedef long long ll;//將long long定義成ll,方便後面書寫
ll tmp[N][N][N];//記錄結果
ll a,b,c,ans;
int dfs(ll x,ll y,ll z)
{
if(x<=0||y<=0||z<=0)
return 1;
else if(x>20||y>20||z>20)
{
x=y=z=20;//防止下標越界,而且對結果沒什麼影響
return dfs(20, 20, 20);
}
else if(tmp[x][y][z])//如果已有出現過的答案,直接輸出
return tmp[x][y][z];
else if(x<y&&y<z)
tmp[x][y][z]=dfs(x,y,z-1)+dfs(x,y-1,z-1)-dfs(x,y-1,z);
else
tmp[x][y][z]=dfs(x-1,y,z)+dfs(x-1,y,z-1)+dfs(x-1,y-1,z)-dfs(x-1,y-1,z-1);
return tmp[x][y][z];//記錄答案
}
int main()
{
while(1)
{
scanf("%lld%lld%lld",&a,&b,&c);
if(a==-1&&b==-1&&c==-1)
return 0;
else
{
ans = dfs(a, b, c);
printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, ans);
}
}
}
```