bzoj 2832 宅男小c

 
Description

众所周知,小C是个宅男,所以他的每天的食物要靠外卖来解决。小C现在有M元钱,他想知道这些钱他最多可以吃多少天。

 

餐厅提供N种食物,每种食物有两个属性,单价Pi和保质期Si,表示小C需要花Pi元才能买到足够一天吃的这种食物,并且需要在送到Si天内吃完,否则食物会变质,就不能吃了,若Si为0则意味着必须在送到当天吃完。另外,每次送餐需要额外F元送餐费。

 

Input

每个测试点包含多组测试数据;
每个测试数据第一行三个整数M,F,N,如题目描述中所述;
以下N行,每行两个整数,分别表示PiSi

Output

对于每个测试数据输出一行,表示最多可以吃的天数。

Sample Input

32 5 2
5 0
10 2
10 10 1
10 10
10 1 1
1 5

Sample Output

3
0
8

HINT

 

【数据规模及约定】

对于40%的数据,M,Si <= 2*10^6;

对于100%的数据,M, Si<= 10^18,1 ≤ T ≤ 50,1 ≤ F ≤ M,1 ≤ N ≤ 200,1 ≤ Pi ≤ M。

 

思路: 本题可以三分。 

题解:
  我不能确保这种方法的正确性,因为迄今为止我还没有看到其他能够复杂度能够承受的办法,最起码这样做的话,
  数据是可以过的,当然不排除数据不够全面。因为送物品非常自由,没有任何限制,所以我们要找一个合适的自变
  量进行枚举。可以发现,如果我们外卖的次数过少,那么就会出现一些食品性价比不高的情况;如果次数过多,
  那么就会浪费外卖运费。故可以从这里入手,因为可以看出这是一个类似于二次函数的函数。我们可以通过三分来查找峰值。
  那么对于每次的求值,就是以贪心为主体了。因为我们显然要价格便宜,保质期又长的食品,故我们将同保质期但
  价格偏高的去除,然后根据保质期从大到小排序,我们给每一次送餐都加上一个该食品,直到钱不够或者时间已经超过。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define rep(i,a,b) for(R i=a;i<=b;i++)
 5 #define Rep(i,a,b) for(R i=a;i>=b;i--)
 6 #define ms(i,a)    memset(a,i,sizeof(a))
 7 #define gc()       getchar()
 8 #define LL         long long
 9 typedef pair<LL,LL>  pi;
10 template<class T>void read(T &x){
11   x=0; char c=0;
12   while (!isdigit(c)) c=gc();
13   while (isdigit(c)) x=x*10+(c^48),c=gc();
14 }
15 int const N=210;
16 LL n,m,f,l,r,len,m1,m2,nn;
17 pi s1,s2,ans;
18 struct node{
19   LL p,s;
20 }a[N];
21 int cmp(node a,node b){
22   return a.s==b.s?  a.p<b.p: a.s> b.s;
23 }
24   
25 pi calc(LL k){
26   LL t=m-f*k,d=0,now=0,j;
27   Rep(i,nn,1){
28     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;
29     if(a[i].s>=d) j=min(t/a[i].p,k),d++,now+=j,t-=j*a[i].p;
30   }
31   return pi(now,t);
32 }
33 
34 int main(){
35   while (scanf("%lld%lld%lld",&m,&f,&n)!=EOF){
36     ans=pi(0,0);
37     rep(i,1,n) read(a[i].p),read(a[i].s); 
38     sort(a+1,a+n+1,cmp);nn=1;                     
39     rep(i,2,n) if(a[nn].s>a[i].s && a[i].p<a[nn].p) a[++nn]=a[i];      
40     l=1,r=m/(f+a[nn].p);
41     while (l<=r){
42       len=(r-l)/3;
43       if( (s1=calc(m1=l+len))>(s2=calc(m2=r-len))) ans=max(ans,s1),r=m2-1;else ans=max(ans,s2),l=m1+1;
44     }
45     cout<<ans.first<<endl;
46   }
47   return 0;
48 }
View Code

 

 
 

 

posted @ 2019-01-10 15:39  zjxxcn  阅读(175)  评论(0编辑  收藏  举报