洛谷 - 1023:稅收與補貼問題

稅收與補貼問題

來源:洛谷

標籤:

參考資料:

相似題目:

題目

每樣商品的價格越低,其銷量就會相應增大。現已知某種商品的成本及其在若干價位上的銷量(產品不會低於成本銷售),並假設相鄰價位間銷量的變化是線性的且在價格高於給定的最高價位後,銷量以某固定數值遞減。(我們假設價格及銷售量都是整數)

對於某些特殊商品,不可能完全由市場去調節其價格。這時候就需要政府以稅收或補貼的方式來控制。(所謂稅收或補貼就是對於每個產品收取或給予生產廠家固定金額的貨幣)

你是某家諮詢公司的項目經理,現在你已經知道政府對某種商品的預期價格,以及在各種價位上的銷售情況。要求你確定政府對此商品是應收稅還是補貼的最少金額(也爲整數),才能使商家在這樣一種政府預期的價格上,獲取相對其他價位上的最大總利潤。

總利潤=單位商品利潤 × 銷量
單位商品利潤=單位商品價格 - 單位商品成本 (- 稅金 or + 補貼)

輸入

輸入的第一行爲政府對某種商品的預期價,第二行有兩個整數,第一個整數爲商品成本,第二個整數爲以成本價銷售時的銷售量,以下若干行每行都有兩個整數,第一個爲某價位時的單價,第二個爲此時的銷量,以一行-1, -1表示所有已知價位及對應的銷量輸入完畢,輸入的最後一行爲一個單獨的整數表示在已知的最高單價外每升高一塊錢將減少的銷量。

輸出

輸出有兩種情況:若在政府預期價上能得到最大總利潤,則輸出一個單獨的整數,數的正負表示是補貼還是收稅,數的大小表示補貼或收稅的金額最小值。若有多解,取絕對值最小的輸出。
如在政府預期價上不能得到最大總利潤,則輸出“NO SOLUTION”。

輸入樣例

31
28 130
30 120
31 110
-1 -1
15

輸出樣例

4

解題思路

理解清楚題意。設補貼或稅收爲常數k(正數爲補貼、負數爲稅收),商品價格爲變量x,對應銷量爲f(x),其中成本爲x0x_{0}、預期價格爲xtx_{t}。按照題意,應滿足
(xtx0+k)f(xt)(xix0+k)f(xi)  i(x_{t}-x_{0}+k)*f(x_{t}) \geqslant (x_{i}-x_{0}+k)*f(x_{i}) \ \ \forall i
數學推導得
k(f(xt)f(xi))(xix0)f(xi)(xtx0)f(xt)  ik*(f(x_{t})-f(x_{i}))\geqslant (x_{i}-x_{0})*f(x_{i})-(x_{t}-x_{0})*f(x_{t}) \ \ \forall i
這是一個關於k的不等式,最終可得到k的範圍。

參考代碼

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=100000;

int expect_price; //預期價格 
int expect_sales; //預期效率 
int price[MAXN]; //價格數組 
int sales[MAXN]; //銷量數組 
int decline; //超過最高價之後的單位減少銷量 
int cnt; //price和sales數組的計數器 

int main(){
	scanf("%d", &expect_price);
	int d1, d2;
	int pre_d1=0, pre_d2=0, k=0; 
	while(scanf("%d%d", &d1, &d2) && d1!=-1){
		if(pre_d1 && pre_d1+1!=d1){ //推算兩個相鄰已知價格間的未知價格的銷量 
			k=(d2-pre_d2)/(d1-pre_d1); //比值,即價格每漲高1元,銷量減少k
			while(++pre_d1<d1){
				pre_d2+=k;
				price[cnt]=pre_d1; sales[cnt]=pre_d2; ++cnt;
				if(pre_d1==expect_price) expect_sales=pre_d2; //記錄預期銷量 
			}
		} 
		if(d1==expect_price) expect_sales=d2;
		price[cnt]=d1; sales[cnt]=d2; ++cnt;
		pre_d1=d1; pre_d2=d2;
	}
	scanf("%d", &decline);
	
	//推算大於已知最高價的其他價格的銷量
	int now_price=price[cnt-1]+1;
	int now_sales=sales[cnt-1]-decline;
	while(now_sales>0){
		if(now_price==expect_price) expect_sales=now_sales; 
		price[cnt]=now_price; sales[cnt]=now_sales; ++cnt;
		now_price+=1; now_sales-=decline;
	}
	
	double left=-MAXN, right=MAXN; //滿足條件的左右端點 
	for(int i=0; i<cnt; ++i){
		if(expect_sales-sales[i]>0){
			left=max(left, ((price[i]-price[0])*sales[i]-(expect_price-price[0])*expect_sales)*1.0/(expect_sales-sales[i]));
		}
		else if(expect_sales-sales[i]<0){
			right=min(right, ((price[i]-price[0])*sales[i]-(expect_price-price[0])*expect_sales)*1.0/(expect_sales-sales[i])); 
		}
	}
	
	if(left>right) printf("NO SOLUTION\n");
	else{
		if(left>=0) printf("%d\n", (int)ceil(left));
		else if(right<=0) printf("%d\n", (int)floor(right));
		else printf("0\n");
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章