正题
题目大意
给出长度为
n
n
n的序列
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d
求一个序列
e
e
e满足
(
∑
i
=
1
n
e
i
∗
c
i
)
=
0
(
e
∈
[
a
i
.
.
b
i
]
)
(\sum _{i=1}^ne_i*c_i)=0(e\in [a_i..b_i])
(i=1∑nei∗ci)=0(e∈[ai..bi])
求
m
a
x
{
∑
i
=
1
n
e
i
∗
d
i
}
max\{\sum_{i=1}^ne_i*d_i\}
max{i=1∑nei∗di}
解题思路
我们把这个转换成一个多重背包问题,拿
a
i
∼
b
i
a_i\sim b_i
ai∼bi个物品,要求价格之和为
0
0
0,且价值最大。
我们可以发现对于每个物品我们都至少
a
i
a_i
ai个,所有我们可以直接把
a
i
a_i
ai个丢进背包里,然后每个物品数量变为
b
i
−
a
i
b_i-a_i
bi−ai个,做多重背包。
要二进制压缩,不然会
T
T
T
c o d e code code
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 210
using namespace std;
int n,m,tmp,num;
int a[N],b[N],c[N],d[N];
int w[10050],v[10050],f[100050];
int main()
{
memset(f,0xcf,sizeof(f));f[0]=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
b[i]-=a[i];tmp+=a[i]*d[i];m-=a[i]*c[i];
}
for(int k=1;k<=n;k++)//二进制压缩
{
for(int i=1;i<=b[k];i*=2)
{
w[++num]=c[k]*i;v[num]=d[k]*i;
b[k]-=i;
}
if(b[k]) w[++num]=b[k]*c[k],v[num]=d[k]*b[k];
}
for(int i=1;i<=num;i++)//背包
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
printf("%d",f[m]+tmp);
}