bzoj 2832 宅男小c
阿新 • • 發佈:2019-01-10
眾所周知,小C是個宅男,所以他的每天的食物要靠外賣來解決。小C現在有M元錢,他想知道這些錢他最多可以吃多少天。
餐廳提供N種食物,每種食物有兩個屬性,單價Pi和保質期Si,表示小C需要花Pi元才能買到足夠一天吃的這種食物,並且需要在送到Si天內吃完,否則食物會變質,就不能吃了,若Si為0則意味著必須在送到當天吃完。另外,每次送餐需要額外F元送餐費。
Input
每個測試點包含多組測試資料; 每個測試資料第一行三個整數M,F,N,如題目描述中所述;Output
對於每個測試資料輸出一行,表示最多可以吃的天數。Sample Input
32 5 25 0
10 2
10 10 1
10 10
10 1 1
1 5
Sample Output
30
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