简单的背包——01背包(9)
题目来源:洛谷 P1926 小书童——刷题大军
共三个测试点
题解
AC代码
#include <bits/stdc++.h>
using namespace std;
// 两次背包
// 第一次选出时间内的分数最大值
// 第二次选出剩下时间内能做的题目数最大值
int n, m, k, r;
// t[x] 表示刷第 x 题所用的时间
int t[15];
// tim[x] 和 val[x] 分别表示做第 x 次作业所用的时间和得到的分值
int tim[15], val[15];
// f[x] 表示 x 时间内所得到的最高分数
// g[x] 表示 x 时间内所做的最多题
int f[155], g[155];
int main()
{
// 初始化
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
// 读入数据
scanf("%d%d%d%d", &n, &m, &k, &r);
for (int i = 1; i <= n; ++i)
scanf("%d", &t[i]);
for (int i = 1; i <= m; ++i)
scanf("%d", &tim[i]);
for (int i = 1; i <= m; ++i)
scanf("%d", &val[i]);
// 01背包 —— 1
for (int i = 1; i <= m; ++i)
{
for (int j = r; j >= tim[i]; --j)
f[j] = max(f[j], f[j - tim[i]] + val[i]);
}
// 将 r 改变成及格后能剩下的最多的时间
r -= (lower_bound(f + 1, f + r + 1, k) - f);
// 01背包 —— 2
for (int i = 1; i <= n; ++i)
{
for (int j = r; j >= t[i]; --j)
g[j] = max(g[j], g[j - t[i]] + 1);
}
printf("%d", g[r]);
return 0;
}