题意分析
小 A 有 n
道喜欢的题目,每道题目需要一定的时间才能完成,对于完成作业,老师布置了 m
项作业,每项作业需要一些时间和能获得一定的分值。完成至少 k
分的作业是及格标准。小 A 希望在有 r
单位时间内,除了完成这些作业外,能尽可能多地做他喜欢的题目。
状态转移方程
- 完成作业的价值:
- 使用动态规划来计算在有
r
单位时间下,最大能获得的分值。定义一个数组dp[r+1]
,其中dp[j]
表示在j
单位时间内能获得的最大分值。 - 对于每项作业
i
(时间为ht[i]
, 分值为hw[i]
),状态转移方程为:
- 使用动态规划来计算在有
dp[j] = max(dp[j], dp[j - ht[i]] + hw[i])
-
检查及格情况:
- 在计算完所有作业的最大分值后,遍历
dp
数组,检查具备及格分数k
的最小时间,更新剩余时间r
。
- 在计算完所有作业的最大分值后,遍历
-
完成题目的数量:
- 对于剩余时间,在可用的时间内做最大数量的题目。定义一个新的动态规划数组
dp1[r+1]
,其中dp1[j]
表示在j
单位时间内能做的题目数量。 - 对于每道题目
i
(需要时间为p[i]
),状态转移方程为:
- 对于剩余时间,在可用的时间内做最大数量的题目。定义一个新的动态规划数组
dp1[j] = max(dp1[j], dp1[j - p[i]] + 1)
C++ 代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
int n, m, k, r;
int p[N]; // 每道题目的时间
int ht[N]; // 每项作业需要的时间
int hw[N]; // 每项作业的分值
int dp[250]; // 动态规划数组
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// 读取输入
cin >> n >> m >> k >> r;
for (int i = 1; i <= n; i++) {
cin >> p[i]; // 题目的时间
}
for (int i = 1; i <= m; i++) {
cin >> ht[i]; // 作业的时间
}
for (int i = 1; i <= m; i++) {
cin >> hw[i]; // 作业的分值
}
// 动态规划计算作业的最大分值
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= m; i++) {
for (int j = r; j >= ht[i]; j--) {
dp[j] = max(dp[j], dp[j - ht[i]] + hw[i]);
}
}
// 找到第一个满足及格条件的时间
for (int i = 1; i <= r; i++) {
if (dp[i] >= k) {
r -= i; // 更新剩余时间
break;
}
}
// 计算在剩余时间内可以做完的题目数量
int dp1[250] = {0}; // 动态规划数组
for (int i = 1; i <= n; i++) {
for (int j = r; j >= p[i]; j--) {
dp1[j] = max(dp1[j], dp1[j - p[i]] + 1);
}
}
// 输出结果
cout << dp1[r] << "\n";
return 0;
}