题目https://www.luogu.com.cn/problem/P2392
解法1:DFS
对于每一科,我们需要将一些题目放入集合 ,其余的放入集合
。
我们设 集合中的元素个数为
,
集合中的元素个数为
,则答案为(
):
用 DFS 实现即可。
实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
int s,a[25],S[5],ans,sum=1e18;
void dfs(int x,int A,int B){
if(x>s){
sum=min(sum,max(A,B));
return;
}
dfs(x+1,A+a[x],B);
dfs(x+1,A,B+a[x]);
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>S[1]>>S[2]>>S[3]>>S[4];
for(int i=1;i<=4;i++){
s=S[i];
for(int j=1;j<=s;j++){
cin>>a[j];
}
sum=1e18;
dfs(1,0,0);
ans+=sum;
}
cout<<ans;
return 0;
}
解法2:动态规划
可以先回顾一下前面的 DFS 写法。
在 DFS 的写法中,我们是将习题册的题目分成集合 和集合
,使得
和
的差最小。
也就是 要尽可能地接近
。
那么 就是背包的容量,每道题的做题时间为物品的价格和价值。
对于第 本习题册:
设 表示前
个物品选择一些放入剩余容量为
的背包中能获得的最大价值。
答案为:。
其中 表示第
本习题册的题目数量,
表示习题册题目用时之和。
设 表示第
道题目需要的时间。
状态转移:
记得清空 数组。
实现
/*
对于第 k 科:
设 dp[i][j] 表示前 i 个物品选择一些放入剩余容量为 j 的背包中能获得的最大价值
答案:max(sum-dp[s[i]][m/2],dp[s[i]][m/2])(m 为习题题目完成时间之和)
状态转移:
如果第 i 个物品能放入背包中(j>=a[i])则:dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i])
a[i] 表示第 i 道习题需要完成多久
否则:dp[i][j]=dp[i-1][j]
初始化:dp[i][j]=0
*/
#include<bits/stdc++.h>
using namespace std;
int s[5],a[25],dp[25][1205],ans;
void code(int n,int m){
fill(dp[0],dp[n+1],0);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=dp[i-1][j];
if(j>=a[i]){
dp[i][j]=max(dp[i][j],dp[i-1][j-a[i]]+a[i]);
}
}
}
return;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>s[1]>>s[2]>>s[3]>>s[4];
for(int i=1;i<=4;i++){
int sum=0;
for(int j=1;j<=s[i];j++){
cin>>a[j];
sum+=a[j];
}
code(s[i],sum/2);
ans+=max(sum-dp[s[i]][sum/2],dp[s[i]][sum/2]);
}
cout<<ans;
return 0;
}