题解 P6433 【「EZEC-1」出题】
RedLycoris · · 题解
首先,我们可以先选择题目,再把剩下不要的让家长拿走。这一定是最优的。
然后就是个基础的背包。dp[i][j]表示考虑带第i个题目时,花费了j个时间的最大毒瘤值。 为了最后的计算,还要记录一下路径。
最后通过记录的路径求出选了那些题目,然后贪心的从大到小排序,选前k个*2即可。
#include<bits/stdc++.h>
using namespace std;
int dp[101][1001],par[101][1001],k;
int a[101],b[101],n,m;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;++i)cin>>a[i]>>b[i];
for(int i=1;i<=n;++i){
for(int j=0;j<=m;++j){
dp[i][j]=dp[i-1][j],par[i][j]=j;
if(j>=b[i]){
if(dp[i][j]<dp[i-1][j-b[i]]+a[i]){
dp[i][j]=dp[i-1][j-b[i]]+a[i];
par[i][j]=j-b[i]; //记录路径
}
}
}
}
vector<int>v;v.clear();
int mx=-1,wz,ans=0;
for(int i=0;i<=m;++i){
if(dp[n][i]>mx){
mx=dp[n][i];
wz=i;
}
}
for(int i=n;i;--i){
int T=par[i][wz];
if(T==wz);
else{
v.push_back(a[i]);
wz=T;
}
}
sort(v.rbegin(),v.rend());
if(!v.size()){ //一个特判
cout<<0<<'\n';
return 0;
}
if(v.size()==n)v.pop_back();
for(int i=0;i<v.size();++i){
if(i<k)ans+=v[i]*2;
else ans+=v[i];
}
cout<<ans<<'\n';
}