[LeetCode 周赛185] 4. 生成数组(暴力、动态规划、巧妙解法)

1. 题目来源

链接:5391. 生成数组

2. 题目说明

在这里插入图片描述
在这里插入图片描述

3. 题目解析

方法一:暴力+动态规划+巧妙解法

数据范围很小,完全可以暴力 dp,也是多数人所采取的方法了。理解题意的话就是 search_cost 代表着从前向后遍历该数组时,同时记录一个最大值 max,这个 search_cost 就是 max 所更新的次数。dp 思路如下:

  • 状态定义:dp[i][p][v]i 个数字,search_cost=p,当前的最大值为 v 的方案数
  • 四重暴力循环顺序递推 dp 数组即可
    • 第一重 for:从 1 到 n 的递推,范围 [1, n]
    • 第二重 for:前一个状态 search_cost=p,范围 [0, k]
    • 第三重 for:前一个状态最大值为l,范围 [0, m]
    • 至此,前三重表示前一个状态,即 dp[i - 1][p][l] 转移到当前状态
    • 第四重 for:当前状态所填的数字 v,范围 [1 m]
  • 在第四重 for 内进行状态更新,即会产生两种情况:
    • v > l 时则最大值需更新,且 search_cost 需加 1
    • v ≤ l 时则不需要进行最大值和 search_cost 的更新

这个 dp,几乎将能算的状态全算出来了,相当暴力。个人感觉理解的重点在于区别前三重 for 的作用是确定上一状态的,第四重 for 表示现在的数字选取及内部状态转移,np 继承上状态的 search_costnv 继承上状态的最大值,然后比较转移即可,确实很直观,但由于循环嵌套确实多,不熟练的也是望而生畏的。

参见代码如下:

// 执行用时 :272 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :9.4 MB, 在所有 C++ 提交中击败了100.00%的用户

#define LL long long
const LL MOD = 1e9 + 7;

// dp[i][k][v] 前i个数字,search_cost=k,当前的最大值为v的方案数
LL dp[55][55][150];

class Solution {
public:
    int numOfArrays(int n, int m, int k) {
        memset(dp, 0, sizeof(dp));
        dp[0][0][0] = 1;

        for (int i = 1; i <= n; ++i) {
            for (int p = 0; p <= k; ++p) {
                for (int l = 0; l <= m; ++l) {
                    for (int v = 1; v <= m; ++v) {
                        int np = p, nv = max(v, l);
                        if (v > l) ++np;
                        dp[i][np][nv] = (dp[i][np][nv] + dp[i - 1][p][l]) % MOD;
                    }
                }
            }
        }
        LL ans = 0;
        for (int v = 1; v <= m; ++v) {
            ans = (ans + dp[n][k][v]) % MOD;
        }

        return ans;
    }
};
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值