题目
Sample Input
1
3 5 1 5
-3 5 2
-2 2 3
2 5 3
Sample Output
9
思路:共有n个广告,一共有2^n个选择方案。假定确定好选择方案了。
利润: ka[x]+b[x]+ka[m]+b[m]+…+ka[r]+b[r]=k(a[x]+a[m]+…+a[r])+(b[x]+b[m]+b[r]);
每一种方案的利润对于k是一个一次函数。共有2^n个一次函数。对于确定的k,每个公司会选择 2 ^n种方案里面的最大利润。即2 ^n个 函数取最高值。将这2 ^n个函数画出来。
(利润关于k的图像)。将每个k对应的最高点连起来。可以看出是个凹函数。故三分得出答案。k对应这个凹函数的值(就是2 ^n个里面取最大值 用01背包完成)。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define en '\n'
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int N=500+5,INF=0x3f3f3f3f;
int n,m,L,R;
ll a[N],b[N],w[N];
ll dp[N];
ll work(int k)
{
m(dp,0);
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+k*a[i]+b[i]);
return dp[m];
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&n,&m,&L,&R);
for(int i=1;i<=n;i++)
scanf("%lld%lld%lld",&a[i],&b[i],&w[i]);
int l=L,r=R,m1,m2;
while(r-l>1)
{
m1=(l+r)/2,m2=(m1+r)/2;
if(work(m1)>work(m2))
l=m1;
else
r=m2;
}
printf("%lld\n",work(r));
}
}