题目链接
题目描述
小红有 个事件可以分享。对于第
个事件,分享需要花费
分钟时间和
点精力,并能获得
点快乐值。小红希望在总耗时不超过
,总消耗精力不超过
的前提下,选择分享若干事件,使得获得的快乐值总和最大。
输入:
- 第一行输入一个整数
,表示事件数量。
- 第二行输入两个整数
和
,表示可用时间和可用精力的上限。
- 接下来
行,每行输入三个整数
,描述第
个事件的参数。
输出:
- 输出一个整数,代表在限制条件内能获得的最大快乐值。
解题思路
本题是一个典型的 二维费用01背包问题。与传统的01背包问题不同,这里每个物品(事件)有两个“费用”或“成本”(时间和精力),而我们要在两个限制条件下求最大价值。
-
状态定义:
- 我们定义一个二维数组
,其中
表示在时间限制为
、精力限制为
的情况下,所能获得的最大快乐值。
- 我们定义一个二维数组
-
状态转移:
- 对于第
个事件(耗时
,耗精力
,快乐值
),我们有两种选择:
- 不选择 该事件:最大快乐值保持不变,与只考虑前
个事件时相同。
- 选择 该事件:前提是当前的时间和精力预算足够,即
且
。如果选择,那么快乐值就是在消耗
时间和
精力前的最大快乐值(即
)基础上,加上当前事件的快乐值
。
- 不选择 该事件:最大快乐值保持不变,与只考虑前
- 因此,状态转移方程为:
- 对于第
-
遍历顺序:
- 为了确保每个事件最多只被选择一次(01背包的特性),我们需要对时间和精力这两个维度进行 逆序遍历。
- 遍历顺序如下:
- 外层循环遍历每个事件
从
到
。
- 中层循环遍历时间
从
到
。
- 内层循环遍历精力
从
到
。
- 外层循环遍历每个事件
-
初始化:
- 我们需要将
数组全部初始化为0,表示在没有任何预算或不选择任何事件时,快乐值为0。
- 我们需要将
最终, 就是我们要求的答案。
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
int T, H;
cin >> T >> H;
vector<vector<long long>> dp(T + 1, vector<long long>(H + 1, 0));
for (int i = 0; i < N; ++i) {
int t, h, p;
cin >> t >> h >> p;
for (int j = T; j >= t; --j) {
for (int k = H; k >= h; --k) {
dp[j][k] = max(dp[j][k], dp[j - t][k - h] + p);
}
}
}
cout << dp[T][H] << "\n";
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int T = sc.nextInt();
int H = sc.nextInt();
long[][] dp = new long[T + 1][H + 1];
for (int i = 0; i < N; i++) {
int t = sc.nextInt();
int h = sc.nextInt();
int p = sc.nextInt();
for (int j = T; j >= t; j--) {
for (int k = H; k >= h; k--) {
dp[j][k] = Math.max(dp[j][k], dp[j - t][k - h] + p);
}
}
}
System.out.println(dp[T][H]);
}
}
N = int(input())
T, H = map(int, input().split())
dp = [[0] * (H + 1) for _ in range(T + 1)]
for _ in range(N):
t, h, p = map(int, input().split())
for j in range(T, t - 1, -1):
for k in range(H, h - 1, -1):
dp[j][k] = max(dp[j][k], dp[j - t][k - h] + p)
print(dp[T][H])
算法及复杂度
- 算法:动态规划 (二维费用01背包)
- 时间复杂度:
- 我们需要遍历
个事件,对于每个事件,都需要更新大小为
的
表。
- 空间复杂度:
- 主要开销是
二维数组。