题解 CF366C Dima and Salad
题目描述
有
现在选用若干个(至少 1 个)水果制作一份特殊的沙拉,沙拉的美味值为所选的水果的美味值的和,沙拉的卡路里值为所选水果的卡路里值的和。
沙拉的美味值恰好是卡路里值的
第一行,两个整数
第二行,包含
第三行,包含
【输出数据】共一行,一个整数,表示最大美味值,若无解则输出
思路分析
看上去就是一个 0/1 背包,但如果只把卡路里值当做质量,把美味值当做价值,在转移时需要考虑两者的关系,也就是需要同时关注 dp 数组的下标和存储值。这看起来无法实现。
既然要求美味值要是卡路里值的
这样就可以当成普通的 0/1 背包来做了。注意
据说这里的转化运用了分数规划的思想。。。
代码实现
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read(){
int res=0;
int f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
res=res*10+ch-'0';
ch=getchar();
}
return res*f;
}
const int maxn=105;
int n,k;
int a[maxn],b[maxn],c[maxn];
int dp[100005],g[100005];
int ans=-1;
signed main(){
n=read(),k=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++)
b[i]=read(),c[i]=a[i]-k*b[i];
for(int i=1;i<=10000;i++){
dp[i]=g[i]=-0x3f3f3f3f;
}
for(int i=1;i<=n;i++){
if(c[i]<0){
for(int j=10000;j>=-c[i];j--){
g[j]=max(g[j],g[j+c[i]]+a[i]);
}
}
else{
for(int j=10000;j>=c[i];j--){
dp[j]=max(dp[j],dp[j-c[i]]+a[i]);
}
}
}
for(int j=10000;j>=0;j--){
ans=max(ans,dp[j]+g[j]);
}
if(ans!=0)
printf("%lld\n",ans);
else
printf("-1\n");
return 0;
}