洛谷P1464. Function 的题解_原创

原题链接

这道题看起来并不难对吧?但是注意到题目有一句话:

这是个简单的递归函数,但实现起来可能会有些问题。当 a , b , c a, b, c a,b,c 均为 15 15 15 时,调用的次数将非常的多。你要想个办法才行。

这说明用普通的照着题目写的方法是行不通的,经过实测,当 a , b , c a, b, c a,b,c 均为 15 15 15 时,1 秒多都出不了结果。

思路

其实这道题只需要记忆化搜索就可以了,所谓记忆化搜索就是将结果存进一个数组,调用时,答案已经被存储,那么可以直接调用结果,从而节省时间

那么我们可以新建一个三维数组answer[25][25][25],来储存结果。answer[x][y][z]代表 w(x, y, z) 的结果。

代码

代码其实很简单,重点在函数 w(a, b, c) 中。

#include <iostream>
#include <algorithm>
#include <cstring>
#define L long long

using namespace std;

L answer[25][25][25];

// 递归函数w,根据输入的三个参数a, b, c计算结果
// 使用记忆化存储中间结果以优化递归调用
L w(L a, L b, L c) {
    if (a <= 0 || b <= 0 || c <= 0) {
        return 1;
    } else if (a > 20 || b > 20 || c > 20) {
        L r = w(20, 20, 20);
        if (answer[20][20][20] == -1)
            answer[20][20][20] = r;
        return r;
    } else if (answer[a][b][c] != -1) {
        return answer[a][b][c];
    } else if (a < b && b < c) {
        L resA = w(a, b, c - 1);
        L resB = w(a, b - 1, c - 1);
        L resC = w(a, b - 1, c);
        answer[a][b][c] = resA + resB - resC;
        if (answer[a][b][c - 1] == -1) 
            answer[a][b][c - 1] = resA;
        if (answer[a][b - 1][c - 1] == -1) 
            answer[a][b - 1][c -1] = resB;
        if (answer[a][b - 1][c] == -1) 
            answer[a][b - 1][c] = resC;
        return answer[a][b][c];
    } else {
        L resA = w(a - 1, b, c);
        L resB = w(a - 1, b - 1, c);
        L resC = w(a - 1, b, c - 1);
        L resD = w(a - 1, b - 1, c - 1);
        answer[a][b][c] = resA + resB + resC - resD;
        
        if (answer[a - 1][b][c] == -1)
            answer[a - 1][b][c] = resA;
        if (answer[a - 1][b - 1][c] == -1)
            answer[a - 1][b - 1][c] = resB;
        if (answer[a - 1][b][c - 1] == -1)
            answer[a - 1][b][c - 1] = resC;
        if (answer[a - 1][b - 1][c - 1] == -1)
            answer[a - 1][b - 1][c - 1] = resD;
        return answer[a][b][c];
    }
}

// 主函数,初始化answer数组并读取输入,调用w函数计算结果并输出
int main()
{   
    L a, b, c;

    memset(answer, -1, sizeof(answer));

    while (cin >> a >> b >> c) {
        if (a == -1 && b == -1 && c == -1) {
            break;
        } else {
            printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, w(a, b, c));
        }
    }
    
    return 0;
}

这样很容易就AC了!

记忆化搜索万岁!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值