HDU-6475-(三分+01背包 好题)

题目
在这里插入图片描述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));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值