解题思路

使用01背包动态规划求解:

  1. 状态定义: 表示前 道题在 分钟内能获得的最大分数
  2. 每道题有三种选择:跳过、部分完成、完整完成
  3. 时间限制为120分钟(2小时)

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> p(n), a(n), q(n), b(n);
    
    // 读取输入
    for (int i = 0; i < n; i++) {
        cin >> p[i] >> a[i] >> q[i] >> b[i];
    }
    
    // dp[i][j]表示前i道题在j分钟内能获得的最大分数
    vector<vector<int>> dp(n + 1, vector<int>(121, 0));
    
    // 动态规划
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= 120; j++) {
            // 跳过当前题目
            dp[i][j] = dp[i-1][j];
            
            // 部分完成
            if (j >= p[i-1]) {
                dp[i][j] = max(dp[i][j], dp[i-1][j-p[i-1]] + a[i-1]);
            }
            
            // 完整完成
            if (j >= q[i-1]) {
                dp[i][j] = max(dp[i][j], dp[i-1][j-q[i-1]] + b[i-1]);
            }
        }
    }
    
    cout << dp[n][120] << endl;
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        int[] p = new int[n];
        int[] a = new int[n];
        int[] q = new int[n];
        int[] b = new int[n];
        
        // 读取输入
        for (int i = 0; i < n; i++) {
            p[i] = sc.nextInt();
            a[i] = sc.nextInt();
            q[i] = sc.nextInt();
            b[i] = sc.nextInt();
        }
        
        // dp[i][j]表示前i道题在j分钟内能获得的最大分数
        int[][] dp = new int[n + 1][121];
        
        // 动态规划
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= 120; j++) {
                // 跳过当前题目
                dp[i][j] = dp[i-1][j];
                
                // 部分完成
                if (j >= p[i-1]) {
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-p[i-1]] + a[i-1]);
                }
                
                // 完整完成
                if (j >= q[i-1]) {
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-q[i-1]] + b[i-1]);
                }
            }
        }
        
        System.out.println(dp[n][120]);
    }
}
def solve():
    n = int(input())
    p, a, q, b = [], [], [], []
    
    # 读取输入
    for _ in range(n):
        pi, ai, qi, bi = map(int, input().split())
        p.append(pi)
        a.append(ai)
        q.append(qi)
        b.append(bi)
    
    # dp[i][j]表示前i道题在j分钟内能获得的最大分数
    dp = [[0] * 121 for _ in range(n + 1)]
    
    # 动态规划
    for i in range(1, n + 1):
        for j in range(121):
            # 跳过当前题目
            dp[i][j] = dp[i-1][j]
            
            # 部分完成
            if j >= p[i-1]:
                dp[i][j] = max(dp[i][j], dp[i-1][j-p[i-1]] + a[i-1])
            
            # 完整完成
            if j >= q[i-1]:
                dp[i][j] = max(dp[i][j], dp[i-1][j-q[i-1]] + b[i-1])
    
    print(dp[n][120])

if __name__ == "__main__":
    solve()

算法及复杂度

  • 算法:动态规划(01背包变种)
  • 时间复杂度:,其中 是题目数量, 是时间上限(120)
  • 空间复杂度:,用于存储 数组