1. 程式人生 > >洛谷 P1464 Function【記憶化搜索】

洛谷 P1464 Function【記憶化搜索】

!= 並且 \n 沒有 輸出格式 16px 描述 pre 鏈接

題目鏈接:https://www.luogu.org/problemnew/show/P1464

題目描述

對於一個遞歸函數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)

這是個簡單的遞歸函數,但實現起來可能會有些問題。當a,b,c均為15時,調用的次數將非常的多。你要想個辦法才行.

/* absi2011 : 比如 w(30,-1,0)既滿足條件1又滿足條件2

這種時候我們就按最上面的條件來算

所以答案為1

*/

輸入格式:

會有若幹行.

並以-1,-1,-1結束.

保證輸入的數在-9223372036854775808~9223372036854775807之間

並且是整數

輸出格式:

輸出若幹行

格式:

[b]w(a,_b,_c)_=_你的輸出(_代表空格)[/b]

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

解題分析:
若僅僅只是按照題目給的意思進行遞歸,會TLE,所以這時就需要進行記憶化搜索了,將搜索過的答案打表儲存起來,要用的時候直接讀取就好了,不用再搜索一遍,這樣省去了很多重復步驟。
#include <cstdio>
#include <iostream>
using namespace std;
#define ll long long

ll ans[25][25][25];

ll w(ll a, ll b, ll c)
{
    if (a <= 0 || b <= 0 || c <= 0)return 1;
    if (a > 20 || b > 20 || c > 20)return w(20, 20, 20);
    if (!ans[a][b][c]) {            //若之前沒有計算過,那麽只能進行搜索
if (a < b&&b < c)return ans[a][b][c] = w(a, b, c - 1) + w(a - 1, b, c - 1) - w(a - 1, b - 1, c - 1); else return ans[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 ans[a][b][c]; //若之前計算過,直接輸出 } int main() { ll a, b, c; while (scanf("%lld%lld%lld", &a, &b, &c) ,a!=-1||b!=-1||c!=-1) { printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, w(a, b, c)); } return 0; }


2018-06-01

洛谷 P1464 Function【記憶化搜索】