BZOJ2832 : 宅男小C

本文介绍了一种通过三分法和贪心策略优化订购外卖次数的方法,确保在预算内获得最多餐食的同时,考虑到食物的保质期。算法首先排除明显不划算的选项,再通过三分法确定订购次数,最后使用贪心策略进行优化。

首先将所有显然不在最优解中的外卖都删去,那么剩下的外卖价格越低,保质期也最短。

考虑三分订外卖的次数,然后贪心求解,每次尽量平均的时候可以做到最优化。

三分的时候,以存活天数为第一关键字,剩余钱数为第二关键字,就能使函数严格上凸,这样才可以保证三分的正确性。

时间复杂度$O(n\log m)$。

 

#include<cstdio>
#include<algorithm>
#define N 210
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PI;
ll m,f,l,r,len,m1,m2;PI s1,s2,ans;
int n,_n,i,j;struct P{ll p,s;}a[N];
bool cmp(const P&a,const P&b){return a.s==b.s?a.p<b.p:a.s>b.s;}
bool cmp2(const P&a,const P&b){return a.s<b.s;}
PI cal(ll k){
  ll t=m-f*k,d=0,now=0,j;
  for(i=1;i<=n;i++){
    if(a[i].s>=d)j=min(t/a[i].p/k,a[i].s-d+1),d+=j,now+=j*k,t-=j*a[i].p*k;
    if(a[i].s>=d)j=min(t/a[i].p,k),d++,now+=j,t-=j*a[i].p;
  }
  return PI(now,t);
}
int main(){
  while(~scanf("%lld%lld%d",&m,&f,&n)){
    for(i=1;i<=n;i++)scanf("%lld%lld",&a[i].p,&a[i].s);
    _n=n,sort(a+1,a+n+1,cmp);
    for(l=a[j=1].p,i=2;i<=n;i++){
      l=min(l,a[i].p);
      if(a[i].s<=a[j].s&&a[i].p>a[j].p)_n--,a[i].s=-1;else j=i; 
    }
    sort(a+1,a+n+1,cmp),n=_n,sort(a+1,a+n+1,cmp2);
    l=1,r=m/(f+a[1].p);
    while(l<=r){
      len=(r-l)/3;
      if((s1=cal(m1=l+len))>(s2=cal(m2=r-len)))ans=max(ans,s1),r=m2-1;else ans=max(ans,s2),l=m1+1;
    }
    printf("%lld\n",ans.first);
    ans=PI(n=0,0);
  }
  return 0;
}

  

转载于:https://www.cnblogs.com/clrs97/p/4845382.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值