#include using namespace std; int s1, s2, s3, s4; //4科的题目数量 //20是每个科目的题目数量上限 //60是每道题消耗的最长时间上限 //题目数据上限为20*60,这里设置为1210,保证不会越界 const int N = 610; //背包的最大容量是 20*60,我们设置1200就可以,但实际上我们只需要一半的容量,就是610就行了。 int w[N], v[N], f[N]; int bag(int n) { int sum = 0; //当前科目中所有习题的时长总和 memset(f, 0, sizeof(f)); for (int i = 1; i <= n; i++) { cin >> w[i]; v[i] = w[i]; //此题中的价值v和重量w是同一个概念,背包上限的是总时间的一半,放入一个习题,就占用了v[i]的时间,产生了v[i]的价值 sum += w[i]; //总时长 } //总时长的一半,就是尽量想办法装满一半的容量 int m = sum / 2; //01背包模板 for (int i = 1; i <= n; i++) for (int j = m; j >= w[i]; j--) // sum/2就是背包的上限,因为一半尽量装满,则不是这半最佳就是另一半最佳。 f[j] = max(f[j], f[j - w[i]] + v[i]); //两半取最大的一半就是本科目的时长 return max(f[m], sum - f[m]); } int main() { //需要考4科 cin >> s1 >> s2 >> s3 >> s4; int ans = bag(s1) + bag(s2) + bag(s3) + bag(s4); //一科一科的整,四个背包最优解的总和 cout << ans << endl; return 0; }