Problem Description
在这里你需要解决一个全世界人类从诞生起就面临的最大的问题——如何发大财。
你是一名电视广告市场的中介。你的工作是给要打广告的公司安排一天的时间去播放他们的广告。这家公司一共拍摄了n个广告片段,每个片段最多只能播放一次,第i个片段需要占据wi秒的档期,在第k天这个片段给这家公司带来的净利润为k×ai+bi。一个片段一旦开始播放就不能掐断。
你需要在[l,r]之间选择一个正整数k,在第k天播放这家公司的广告。这家公司在你告知k后,会斟酌着选择一些广告进行播放,使得他们的总收益最大(也可能一个广告都不播放,如果都是负收益的话)。电视每天最多只能播放总长度不超过m秒的广告,所以当档期不足时,他们也会酌情舍弃一些广告。
商业竞争是残酷的,对方赚的越多,你赚的就越少。请选择一个最合适的k,使得该公司按照最优策略投放广告的总收益最小。
你是一名电视广告市场的中介。你的工作是给要打广告的公司安排一天的时间去播放他们的广告。这家公司一共拍摄了n个广告片段,每个片段最多只能播放一次,第i个片段需要占据wi秒的档期,在第k天这个片段给这家公司带来的净利润为k×ai+bi。一个片段一旦开始播放就不能掐断。
你需要在[l,r]之间选择一个正整数k,在第k天播放这家公司的广告。这家公司在你告知k后,会斟酌着选择一些广告进行播放,使得他们的总收益最大(也可能一个广告都不播放,如果都是负收益的话)。电视每天最多只能播放总长度不超过m秒的广告,所以当档期不足时,他们也会酌情舍弃一些广告。
商业竞争是残酷的,对方赚的越多,你赚的就越少。请选择一个最合适的k,使得该公司按照最优策略投放广告的总收益最小。
Input
第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。
每组数据第一行包含四个正整数n,m,l,r(1≤n,m≤500,1≤l≤r≤106),分别表示广告片段的数量、档期的限制以及选择的范围。
接下来n行,每行三个整数ai,bi,wi(−106≤ai≤106,−1012≤bi≤1012,1≤wi≤m),依次描述每个广告片段。
每组数据第一行包含四个正整数n,m,l,r(1≤n,m≤500,1≤l≤r≤106),分别表示广告片段的数量、档期的限制以及选择的范围。
接下来n行,每行三个整数ai,bi,wi(−106≤ai≤106,−1012≤bi≤1012,1≤wi≤m),依次描述每个广告片段。
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; }