Function(记忆化搜索)

文章讨论了一种递归函数的优化问题,通过记忆化搜索技术,避免重复计算,尤其是在a、b、c参数空间较大时。作者给出了代码示例,展示了如何使用一个三维数组存储已计算结果,以提高算法效率。
摘要由CSDN通过智能技术生成

题目描述

对于一个递归函数 w(a,b,c)


- 如果 a <= 0 或 b <= 0 或 c <= 0 就返回值 1。
- 如果 a>20 或 b>20 或 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 时,调用的次数将非常的多。你要想个办法才行。

注意:例如 w(30,-1,0) 又满足条件1 又满足条件 2,请按照最上面的条件来算,答案为 1。

输入格式

会有若干行。

并以 -1,-1,-1 结束。

输出格式

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

`w(a, b, c) = ans`

注意空格。

样例 #1

样例输入 #1
1 1 1
2 2 2
-1 -1 -1

样例输出 #1
w(1, 1, 1) = 2
w(2, 2, 2) = 4

提示

数据规模与约定

保证输入的数在 [-9223372036854775808,9223372036854775807] 之间,并且是整数。

保证不包括 -1, -1, -1 的输入行数 T 满足 1 <= T <=10 ^ 5。

如果用普通的递归的话,肯定是会超时的,这道题我们可以考虑记忆化搜索。

题目中提到:调用的次数将非常的多,你要想个办法才行

题目末尾又提到了记忆化搜索

因此,使用记忆化搜索完成此题已经是很明显的了。

记忆化搜索时一定要先想,记忆化的数组要开多大。对于这个题来说,输入数据在long long范围内,对于每一组a,b,c都使用一个变量来进行记忆化是不现实的。

阅读递归函数内容,我们发现,当a<0||b<0||c<0时,返回值都是1,当a>20||b>20||c>20时,返回值都是w(20,20,20),因此,对于以上的这些数据,我们可以不进行记忆化处理。 到了这里,记忆化的数组范围显而易见了,开[30][30][30]的数组绝对够用了。

先看代码。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int rbg[25][25][25];
bool vis[25][25][25];
int w(ll a, ll b, ll c)
{
    if (a <= 0 || b <= 0 || c <= 0)
        return 1;
    else if (a > 20 || b > 20 || c > 20)
        return w(20, 20, 20);
    else if (vis[a][b][c])
        return rbg[a][b][c];
    else if (a < b && b < c)
        rbg[a][b][c] = w(a, b, c - 1) + w(a, b - 1, c - 1) - w(a, b - 1, c);
    else
        rbg[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);
    vis[a][b][c] = true;
    return rbg[a][b][c];
}
int main()
{
    ll a, b, c;
    memset(vis, false, sizeof(vis));
    cin >> a >> b >> c;
    while (a != -1 or b != -1 or c != -1)
    {
        printf("w(%lld, %lld, %lld) = %d\n", a, b, c, w(a, b, c));
        scanf("%lld %lld %lld", &a, &b, &c);
    }
    return 0;
}

下面介绍一下记忆化搜索。

记忆化搜索(Memoization)是一种优化技术,用于避免重复计算,特别是在递归问题中。它通过保存已经计算过的结果,以便在后续的计算中直接使用,从而减少重复的计算。

在我的代码中,我使用了一个名为 rpt 的三维数组来保存已经计算过的结果。这个数组的维度与递归函数的参数对应,即 rpt[a][b][c] 表示在给定参数 abc 下,递归函数 w(a, b, c) 的计算结果。如果在之前的计算中已经计算过这个结果,就直接从 rpt 数组中获取,避免了重复的计算。

在递归函数 w(a, b, c) 中,每次计算结果之后,我都将结果存储在 rpt[a][b][c] 中,以便后续的计算中可以直接使用。这样,当我需要再次计算相同的参数组合时,就可以直接从 rpt 数组中获取结果,而无需重新计算一遍。

记忆化搜索的核心思想是:如果我们在递归过程中遇到了重复的子问题,就可以将这些子问题的计算结果保存下来,避免重复计算,从而提高算法效率。

在我的代码中,这部分实现体现在以下几个地方:

  1. 在递归函数 w(a, b, c) 内部,首先检查是否已经计算过这个参数组合,如果是则直接返回保存的结果。
  2. 在每次计算出递归函数的结果后,将结果存储在 rpt[a][b][c] 中,以便下次直接使用。

通过这种方式,我实现了对递归计算结果的保存和复用,从而提高了程序的效率。记忆化搜索在许多递归问题中都是一个有用且有效的优化方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值