zoukankan      html  css  js  c++  java
  • 商业竞争 三分+背包

      

    Problem Description

    在这里你需要解决一个全世界人类从诞生起就面临的最大的问题——如何发大财。

    你是一名电视广告市场的中介。你的工作是给要打广告的公司安排一天的时间去播放他们的广告。这家公司一共拍摄了n个广告片段,每个片段最多只能播放一次,第i个片段需要占据wi秒的档期,在第k天这个片段给这家公司带来的净利润为k×ai+bi。一个片段一旦开始播放就不能掐断。

    你需要在[l,r]之间选择一个正整数k,在第k天播放这家公司的广告。这家公司在你告知k后,会斟酌着选择一些广告进行播放,使得他们的总收益最大(也可能一个广告都不播放,如果都是负收益的话)。电视每天最多只能播放总长度不超过m秒的广告,所以当档期不足时,他们也会酌情舍弃一些广告。

    商业竞争是残酷的,对方赚的越多,你赚的就越少。请选择一个最合适的k,使得该公司按照最优策略投放广告的总收益最小。

    Input

    第一行包含一个正整数T(1T10),表示测试数据的组数。

    每组数据第一行包含四个正整数n,m,l,r(1n,m500,1lr106),分别表示广告片段的数量、档期的限制以及选择的范围。

    接下来n行,每行三个整数ai,bi,wi(106ai106,1012bi1012,1wim),依次描述每个广告片段。

    Output

    对于每组数据输出一行一个整数,即该公司按照最优策略投放广告的总收益的最小可能值。

    Sample Input

    1
    3 5 1 5
    -3 5 2
    -2 2 3
    2 5 3

    Sample Output

    9

    不会做 参考了大佬

    很显然 如果知道k那么就是一个背包问题 枚举k的话肯定是超时的
    可以在坐标轴做图 x代表k 最优解是最上面那一段 很明显是一个凹函数
    求凹函数的最值用到三分查找法
    现在规定一下二分或者三分查找
    while(l+1<r) 如果把+1去掉是不对的 可能进入死循环
    然后 如果判断条件蕴含等于(可以是小于等于 或者大于等于) 将其往左靠
    也就是 如果是(小于等于 或 大于等于) l=mid else r=mid
    这样最后的答案肯定就是l了


    还有就是注意数据范围!!!
    #include<bits/stdc++.h>
    using namespace std;
    //input
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m);
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N 500+5
    int n,m,l,r;
    ll a[N];
    ll b[N];
    ll w[N];
    ll v[N];
    ll bag(int t)
    {
        rep(i,1,n)
        v[i]=a[i]*t+b[i];
        ll dp[505];
        CLR(dp,0);
        rep(i,1,n)
        repp(j,m,0)
        if(j>=w[i])
            dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        return dp[m];
    }
    
    int main()
    {
        int cas;
        RI(cas);
        while(cas--)
        {
            RIII(n,m,l);RI(r);
            rep(i,1,n)
                cin>>a[i]>>b[i]>>w[i];
    
            while(l+1<r)
            {
                int mid=(l+r)>>1;
                int mmid=(mid+r)>>1;
                if(bag(mid)<bag(mmid))
                     r=mmid;
                else l=mid;//l包含着等于  所以答案会往l靠近
            }
            printf("%lld
    ",bag(l));
        }
        return 0;
    }
    View Code
    
    
  • 相关阅读:
    poj3041——最小点覆盖
    高斯消元
    hdu1704——floyd
    poj2594——最小路径覆盖
    POJ3020 二分图匹配——最小路径覆盖
    我的老博客
    [ZJOI2015]幻想乡战略游戏 动态点分治
    HDU 5737 Differencia set + 主席树
    HDU
    HDU
  • 原文地址:https://www.cnblogs.com/bxd123/p/10661178.html
Copyright © 2011-2022 走看看