传送门
贪心题:既然是算较短的时间,如果左脑所用时间少就加在左脑,如果右脑所用时间少就加在右脑。
#include<bits/stdc++.h>
using namespace std;
int a[5],i,j,sum1,sum2,t,homework;
int main(){
for(i=1;i<=4;i++)
cin>>a[i];//输入
for(i=1;i<=4;i++){
sum1=sum2=0;//两边脑子时间清零
for(j=1;j<=a[i];j++)
{cin>>homework;
if(sum1<=sum2) sum1+=homework;
else sum2+=homework;}//哪边时间短就加在哪边
t+=max(sum1,sum2);//取较长时间累加
}cout<<t;//输出
return 0;
}
提交后发现贪心全错。
果然,贪心不是正解。
后来思考了一下,便感觉是dp,对于一道题只有两个状态,一是加到左脑,二是加到右脑,所以是01背包(背包的体积就是这个科目总耗时的1/2,价值和消耗都是某道题所需花费的时间)。
另外还需要知道:将一边的脑子加到最接近一半(背包问题解决),用总时间减去其,得到另一边脑子时间,后者就是正解。因为有四个科目,所以做四次背包,每次背包结束之后记得dp数组清零。
#include<bits/stdc++.h>
using namespace std;
int a[5]; //记录四个科目每科分别有几题
int b[5][30]; //记录某一科某一题目所花费时间
int sum[5]; //记录某一科的所有题目时间总和
int dp[3000]; //记录某时间段内题目所花费的时间最大值
int ans;
int main()
{
for (int i = 1; i <= 4; i++) {
cin >> a[i];
}
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= a[i]; j++) {
cin >> b[i][j];
sum [i]+= b[i][j];
}
}
for (int k = 1; k <= 4; k++) { //对于某一科目
for (int i = 1; i <= a[k]; i++) { //题号,相当于物品号
for (int j = sum[k] / 2; j >= 0; j--) { //时间,相当于背包容量
if (j >= b[k][i]) { //如果背包容量大于等于该物品重量
dp[j] = max(dp[j], dp[j - b[k][i]] + b[k][i]); //不选或选
}
}
}
ans += sum[k] - dp[sum[k] / 2];
memset(dp, 0, sizeof(dp));
}
cout << ans << endl;
return 0;
}
学会了就来练习一下这道题吧!~
和上一道题非常非常相似,只不过这里直接输出dp[sum / 2]就行啦(因为小柔拿的是少的那一份)~
代码
#include<bits/stdc++.h>
using namespace std;
int n; //珠宝个数
int a[3010]; //记录各个珠宝的价值
int sum; //所有珠宝的价值总和
int dp[3010]; //01背包数组
int main()
{
while (cin >> n) {
//输入
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
//01背包
for (int i = 1; i <= n; i++) {
for (int j = sum / 2; j >= 0; j--) {
if (j >= a[i]) { //如果背包容量大于等于该物品重量
dp[j] = max(dp[j], dp[j - a[i]] + a[i]); //不装或装
}
}
}
cout << dp[sum / 2] << endl;
//清零
memset(dp, 0, sizeof(dp));
sum = 0;
}
return 0;
}