題目連接:https://www.luogu.org/problemnew/show/P1023c++
題目背景
每樣商品的價格越低,其銷量就會相應增大。現已知某種商品的成本及其在若干價位上的銷量(產品不會低於成本銷售),並假設相鄰價位間銷量的變化是線性的且在價格高於給定的最高價位後,銷量以某固定數值遞減。(咱們假設價格及銷售量都是整數)spa
對於某些特殊商品,不可能徹底由市場去調節其價格。這時候就須要政府以稅收或補貼的方式來控制。(所謂稅收或補貼就是對於每一個產品收取或給予生產廠家固定金額的貨幣)code
題目描述
你是某家諮詢公司的項目經理,如今你已經知道政府對某種商品的預期價格,以及在各類價位上的銷售狀況。要求你肯定政府對此商品是應收稅仍是補貼的最少金額(也爲整數),才能使商家在這樣一種政府預期的價格上,獲取相對其餘價位上的最大總利潤。blog
總利潤 = 單位商品利潤 $\times$ 銷量ci
單位商品利潤 = 單位商品價格 - 單位商品成本 (- 稅金 or + 補貼)get
輸入輸出格式
輸入格式:
輸入的第一行爲政府對某種商品的預期價,第二行有兩個整數,第一個整數爲商品成本,第二個整數爲以成本價銷售時的銷售量,如下若干行每行都有兩個整數,第一個爲某價位時的單價,第二個爲此時的銷量,以一行 $-1,-1$ 表示全部已知價位及對應的銷量輸入完畢,輸入的最後一行爲一個單獨的整數表示在已知的最高單價外每升高一塊錢將減小的銷量。產品
輸出格式:
輸出有兩種狀況:若在政府預期價上能獲得最大總利潤,則輸出一個單獨的整數,數的正負表示是補貼仍是收稅,數的大小表示補貼或收稅的金額最小值。如有多解,取絕對值最小的輸出。it
如在政府預期價上不能獲得最大總利潤,則輸出「NO SOLUTION」。ast
輸入輸出樣例
輸入樣例#1:
31
28 130
30 120
31 110
-1 -1
15
輸出樣例#1:
4
說明
全部數字均小於100000class
題解:
首先,不妨計算出從「成本價」到「銷量爲零的價格」,全部整數單價以及其對應的銷量。
設成本價爲 $p$,目標售價爲 $T_{價格}$ 及其對應銷量爲 $T_{銷量}$,全部可能的售價爲 $P_{價格}$ 及其對應銷量爲 $P_{銷量}$,假設補貼(稅收)爲 $x$,則有:
$(T_{價格}-p+x)T_{銷量} \ge (P_{價格}-p+x)P_{銷量}$
化爲:
$x(T_{銷量} - P_{銷量}) \ge (P_{價格}-p)P_{銷量} - (T_{價格}-p)T_{銷量}$
所以,當 $T_{銷量} - P_{銷量} > 0 $ 時,爲 $x \ge [(P_{價格}-p)P_{銷量} - (T_{價格}-p)T_{銷量}] / (T_{銷量} - P_{銷量})$;
當 $T_{銷量} - P_{銷量} < 0 $ 時,爲 $x \le [(P_{價格}-p)P_{銷量} - (T_{價格}-p)T_{銷量}] / (T_{銷量} - P_{銷量})$;
這樣一來,全部的不等式聯立起來,就對 $x$ 有一個區間限定 $[L,R]$,根據這個區間限定選擇輸出答案便可。
AC代碼:
#include<bits/stdc++.h> using namespace std; typedef pair<int,double> P; const double eps=1e-8; vector<P> v; P t; int lst,d; inline bool equ(double a,double b) { return fabs(a-b)<eps; } int main() { cin>>t.first; t.second=0; P tmp; while(cin>>tmp.first>>tmp.second) { if(tmp.first==-1 && tmp.second==-1) break; v.push_back(tmp); } sort(v.begin(),v.end()); lst=v[0].first; for(int i=0,j=1,sz=v.size(); j<sz; i++,j++) { double a=(v[i].second-v[j].second)/(v[i].first-v[j].first); double b=v[i].second-v[i].first*a; for(int x=v[i].first+1;x<v[j].first;x++) v.push_back(make_pair(x,a*x+b)); } sort(v.begin(),v.end()); cin>>d; while(1) { P last=v.back(); if(last.second-d>0) v.push_back(make_pair(last.first+1,last.second-d)); else break; } //for(auto x:v) printf("%d %f\n",x.first,x.second); int pos=lower_bound(v.begin(),v.end(),t)-v.begin(); t=v[pos]; //printf("%d %f\n",t.first,t.second); double L=-1e11,R=1e11; for(auto p:v) { if(p==t) continue; if(t.second>p.second) { L=max(L,((p.first-lst)*p.second-(t.first-lst)*t.second)/(t.second-p.second)); } if(t.second<p.second) { R=min(R,((p.first-lst)*p.second-(t.first-lst)*t.second)/(t.second-p.second)); } } //printf("%f %f\n",L,R); if(L>R) printf("NO SOLUTION\n"); else if(L>0) printf("%.0f\n",ceil(L)); else if(R<0) printf("%.0f\n",floor(R)); else printf("0\n"); }