动态规划之考试策略

13 篇文章 0 订阅
5 篇文章 0 订阅

考试策略

你有一场考试,考试时间为 120 分钟。考试有多道题目,你的作答顺序不受限制。对于第 i 道题目,你有三种不同的策略可以选择:

直接跳过这道题目,不花费时间,本题得 0 分。
只做这道题目一部分,花费 p[i] 分钟的时间,本题可以得到 part[i] 分。
做完整道题目,花费 f[i] 分钟的时间,本题可以得到 full[i] 分。
依次给定 4 个数组:p,part,f,full,请你计算出你最多能得到多少分。

 样例 1:
 输入:
 	p=[20,50,100,5], part=[20,30,60,3], f=[100,80,110,10], full=[60,55,88,6]
 输出:
 	94
 解释: 
 		在所有做题选择中,选择完成整道第 3 题和整道第 4 题的得分最高。整道第 3 题
 	耗时 110 分钟得到 88 分,整道第 4 题耗时 10 分钟得到 6 分,总共耗时 120 分
 	钟得到 94 分。
 	
 样例 2:
 输入:
 	p=[60,60], part=[30,30], f=[100,120], full=[40,60]
 输出:
 	60
 解释: 
 		2 道题目都做一部分和做完整道第 2 题,都能在耗时 120 分钟下得到最高的 60
 	分。

解答:
定义dp[i][j]为题目数量为i,剩余时间为j时,能得到的最大分数:
对于第i道题:
1. 若不做:
dp[i][j] = dp[i-1][j];
2. 若全做:
dp[i][j] = dp[i-1][j-f[i-1]] + full[i-1] {j >= f[i-1]}
3. 若做一部分:
dp[i][j] = dp[i-1][j-p[i-1]] + part[i-1] {j >= p[i-1]}
4. dp[i][j]取值为 1,2,3三者中最大值

class Solution {
public:
    /**
     * @param p: The time you choose to do part of the problem.
     * @param part: The points you choose to do part of the problem.
     * @param f: The time you choose to do the whole problem.
     * @param full: The points you choose to do the whole problem.
     * @return: Return the maximum number of points you can get.
     */
    int exam(vector<int> &p, vector<int> &part, vector<int> &f, vector<int> &full) {
        // write your code here
        
        /*
        定义dp[i][j]为题目数量为i,剩余时间为j时,能得到的最大分数:
        对于第i道题:
            1. 若不做:
                dp[i][j] = dp[i-1][j];
            2. 若全做:
                dp[i][j] = dp[i-1][j-f[i-1]] + full[i-1] {j >= f[i-1]}
            3. 若做一部分:
                dp[i][j] = dp[i-1][j-p[i-1]] + part[i-1] {j >= p[i-1]}
            4. dp[i][j]取值为 1,2,3三者中最大值
        */
        
        int m = p.size() + 1;
        int n = 120 + 1;
        
        int **dp = new int*[m];
        for (int i = 0; i < m; i++) {
            dp[i] = new int[n];
            for (int j = 0; j < n; j++) {
                dp[i][j] = 0;
            }
        }
        
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                int nFull = 0;
                int nPart = 0;
                if(j >= f[i-1]){
                    nFull = dp[i-1][j-f[i-1]] + full[i-1];
                }
                if(j >= p[i-1]){
                    nPart = dp[i-1][j-p[i-1]] + part[i-1];
                }
                dp[i][j] = std::max(dp[i-1][j], std::max(nFull, nPart));
            }
        }
        
        int nMax = dp[m-1][n-1];
        for (int i = 0; i < m; i++) {
            delete[] dp[i];
        }
        delete[] dp;
        return nMax;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值