洛谷—P2392 kkksc03考前临时抱佛脚
题目背景
kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。
输入输出样例
输入
1 2 1 3
5
4 3
6
2 4 3
输出
20
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a,b,c,d;//对应s1,s2,s3,s4
int ans;//最后消耗的总时间
int fun(int a){
//f数组是背包
int a1[25],f[2000]={0};
int m=0;
//m求出总时间
for(int i=0;i<a;i++) cin>>a1[i],m+=a1[i];
//如果只有一个题目
if(a==1) return a1[0];
//有两个题目
else if(a==2) return a1[1]>a1[0]?a1[1]:a1[0];
else {
for(int i=0;i<a;i++){
for(int j=m/2;j>=a1[i];j--){
f[j]=max(f[j],f[j-a1[i]]+a1[i]);
}
}
return max(f[m/2],m-f[m/2]);
}
}
int main(){
cin>>a>>b>>c>>d;
ans=fun(a)+fun(b)+fun(c)+fun(d);
cout<<ans;
return 0;
}
思路
如果一个科目中只有一个题目,那么这一科的时间就是这个题目的时间;如果这个科目中有两个题目,那么这一科的时间就是这两个题目时间中较大的那一个。
当这个科目中的题目大于两道时,设这个科目的总时间是t,那么最优时间是t/2,也就是同时做两个科目的时间差为0。于是现在要求的问题就是使得两边脑所耗时间差尽量小。
如果只考虑一个科目消耗时,由于两边是对称的,我们假设这个耗时肯定比t/2小。那么我们要使这个耗时尽量接近t/2。
然后又想到了背包。保证比t/2小,又要使取得的价值尽量大,可以转化为一个费用与价值相同的背包问题。背包大小为t/2,一个题目的费用和价值相等,都是所耗的时间。
假设背包求得的最大价值为v,显然另一个科目耗时为t-v,则总耗时为max(v,t-v)。