洛谷 P15800:[GESP202603 六级] 选数 ← 动态规划

【题目来源】
https://www.luogu.com.cn/problem/P15800

【题目描述】

【输入格式】
第一行,一个正整数,表示数组长度。
第二行,n 个正整数 a1, a2, ..., an,表示数组 a。
第三行,n 个正整数 b1, b2, ..., bn,表示数组 b。

【输出格式】
一行,一个整数,表示在满足下标条件的前提下,数组 a 对应下标的整数之和的最大值。

【输入样例】
6
1 1 4 5 1 4
1 2 3 2 1 0

【输出样例】
11

【数据范围】
对于 40% 的测试点,保证 2≤n≤10^3。
对于所有测试点,保证 2≤n≤10^5,0≤ai≤10^9,0≤bi≤n。

【算法分析】
● 闫氏 DP 分析法:https://www.bilibili.com/video/BV1X741127ZM
● 最后一步法:https://www.bilibili.com/video/BV1xb411e7ww
● 解题思路(来源于:https://mp.weixin.qq.com/s/MzuV2CmidkGD5I-EMGS28A
这是一个典型的带跳跃限制的动态规划问题。如果我们当前选择位置 i,那么下一个可选择的位置必须满足 j≥i+bi。因此,可以从 i 跳到区间 i+b\[i, n]。
(1)状态定义
设 fi 表示当第一个选择的位置是 i 时,能够获得的最大收益。
(2)状态转移
如果选择了 i,下一步可以选任意 j∈i+b\[i, n]。
于是:fi=ai+max(fj) (其中 j≥i+bi
如果 i+bi>n,说明后面不能再选。此时,有 fi=ai
(3)优化
直接枚举 j 会变成 O(n²)。我们可以维护一个后缀最大值数组 mxi = max(fi, fi+1, ..., fn)。这样就能 O(1) 得到 max(fj),当 j≥i+bi=mxi+b\[i] 时。
于是转移方程优化为:当 i+bi<=n时,fi=ai+mxi+b\[i]。否则,fi=ai
(4)最终答案
因为可以从任意位置开始,答案就是 max(f1, f2, ..., fn)。
复杂度分析:DP 计算 O(n),空间复杂度 O(n)。整体复杂度 O(n),完美通过。

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N=1e5+5;
int a[N],b[N];
LL f[N],ans;
int n;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];
    for(int i=1; i<=n; i++) cin>>b[i];
    for(int i=1; i<=n; i++) {
        ans=max(ans,f[i]+a[i]);
        if(i+b[i]<=n) {
            f[i+b[i]]=max(f[i+b[i]],f[i]+a[i]);
        }
        f[i+1]=max(f[i+1],f[i]);
    }
    cout<<ans;

    return 0;
}

/*
in:
6
1 1 4 5 1 4
1 2 3 2 1 0

out:
11
*/

【参考文献】
https://gesp.ccf.org.cn/101/attach/1734457386074144.pdf
https://blog.csdn.net/hnjzsyjyj/article/details/113549272
https://mp.weixin.qq.com/s/MzuV2CmidkGD5I-EMGS28A
https://mp.weixin.qq.com/s/xPLBl-FiJOvgF83-lqbGTA

相关推荐
Logic1019 小时前
C语言/数据结构动态规划题解:Kadane算法求最大子数组和——O(n)时间O(1)空间
c语言·数据结构·动态规划·贪心·时间复杂度·算法题·最大子数组和
梦帮科技1 天前
AI 音乐产品的发布工程:验证门、数据发布、回滚与生产运维纪律
数据结构·数据库·架构·node.js·音视频·动态规划·推荐算法
语戚1 天前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木1 天前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划
这料鬼有毒1 天前
二刷hot100-1143.最长公共子序列
算法·leetcode·动态规划
Tisfy2 天前
LeetCode 1477.找两个和为目标值且不重叠的子数组:滑动窗口 + 记录前值(动态规划)
动态规划·题解·dp·滑动窗口
ynchyong2 天前
动态规划解题思路:入门篇
动态规划
Tisfy3 天前
LeetCode 2472.不重叠回文子字符串的最大数目:动态规划(贪心)
动态规划·字符串·题解·贪心·dp·回文字符串
青山木4 天前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
Logic1015 天前
C语言/数据动态规划题解:翻转一次子数组后的最大子数组和——四状态DP(O(n)时间O(1)空间)
c语言·数据结构·动态规划·时间复杂度·算法题·状态机dp·最大子数组和