周赛5982. 解决智力问题

本文介绍了一种利用动态规划解决特定考试得分问题的方法。在该问题中,考生需按顺序面对一系列题目,每题可选择解答或跳过,解答一题会获得分数并跳过后续若干题目。文章详细阐述了状态转移方程,并提供了C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给你一个下标从 0 开始的二维整数数组 questions ,其中 questions[i] = [pointsi, brainpoweri] 。

这个数组表示一场考试里的一系列题目,你需要 按顺序 (也就是从问题 0 开始依次解决),针对每个问题选择 解决 或者 跳过 操作。解决问题 i 将让你 获得 pointsi 的分数,但是你将 无法 解决接下来的 brainpoweri 个问题(即只能跳过接下来的 brainpoweri 个问题)。如果你跳过问题 i ,你可以对下一个问题决定使用哪种操作。

比方说,给你 questions = [[3, 2], [4, 3], [4, 4], [2, 5]] :
    如果问题 0 被解决了, 那么你可以获得 3 分,但你不能解决问题 1 和 2 。
    如果你跳过问题 0 ,且解决问题 1 ,你将获得 4 分但是不能解决问题 2 和 3 。

请你返回这场考试里你能获得的 最高 分数。

提示:

1 <= questions.length <= 105
questions[i].length == 2
1 <= pointsi, brainpoweri <= 105

思路

对于数组中的每一项,都有两种情况发生:

  • 该问题解决
  • 该问题放弃

并且对于每一项,接下来他可能接下来处理不同的问题(跳过brainpoweri项到达j后,可能完成j;或忽略j,完成j+1等等),并且最终要求得到一个最值。这很明显可以用动态规划(dp)的思想来进行处理。

dp的核心思想是穷举+消除重复操作
我们可以首先从前向后进行穷举,以[[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7]]为例,从第一项开始:
若[1,1]执行后,它跳到[3,3],此时它可以接下来执行[3,3],[4,4],[5,5],[6,6],[7,7]
若[1,1]跳过,[2,2]执行,他跳到[5,5],,此时它可以接下来执行[5,5],[6,6],[7,7]
此时我们发现,[5,5],[6,6],[7,7]这三项是重复的,因此我们可以从后向前将每一项的数值进行记录,这样就可以消除重复操作
因为题目是要求取最大值,因此我们记录的是这一项和后面项按规则解决后的最大值。

首先建立数组ans存储i项和后面项按规则解决后的最大值,我们从最后一项进行思考:
作为最后一项len-1,此时最大值只能是questions[len-1][0]本身
往前一项len-2,此时的最大值应该是它本身或者len-1这一项的最大值(因为当问题转到这一项后,可以跳过它解决最后一项去)
到i项,此时的最大值应该是它本身questions[i][0]加上它解决后将要跳转项i+questions[i][1]+1的最大值ans[i+questions[i][1]+1],或者是i的后一项的最大值。
此时状态转移方程为:
在这里插入图片描述

代码

class Solution {
public:
    long long mostPoints(vector<vector<int>>& questions) {
        int len = questions.size();
        vector<long long> ans(len+1);
        long long maxx = 0;
        for(int i=len-1;i>=0;i--){
            int num =  i+questions[i][1]+1;
            if(num<len)
                ans[i] = max(ans[num]+questions[i][0], ans[i+1]);
            else
                ans[i] = max((long long)questions[i][0], ans[i+1]);
            maxx = max(maxx, ans[i]);
        }
        return maxx;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值