原題連結:https://www.luogu.com.cn/problem/P1023
題意解讀:給定商品單價和對應銷量表,計算使得采用預期價格銷售得到最大利潤時的最小補貼或者稅收。
解題思路:
1、樣例模擬
31
28 130
30 120
31 110
-1 -1
15
政府預期價格:31
商品成本:28,按成本價售賣銷量:130
商品單價:30,對應銷量:120
商品單價:31:對應銷量:110
超出商品最高單價31後,每增加一元,銷量降低15
要計算預期價帶來的總利潤是否最大,就要和所有價格帶來的總利潤進行比較,因此需要將商品單價從28以上銷量不為0的資料都補充完整
比如:28和30元之間有29元,根據銷量是線性的得知29元的銷量是130 - (130 - 120) / 2 = 125
然後針對31元以上的銷量每增加一元減少15進行補充,最終得到單價-銷量表:
28 130
29 125
30 120
31 110
32 95
33 80
34 65
35 50
36 35
37 20
38 5
再分別列舉補貼和稅收,補貼從1~100000,稅收從-1到-100000
如果找到一個補貼,使得按照預期價格銷售的總利潤最大,則記錄補貼值
如果找到一個稅收,使得按照預期價格銷售的總利潤最大,則記錄稅收值
最後根據補貼和稅收的值,輸出絕對值較小的
2、演算法總結
第一步:構建一個價格-銷量表,價格從成本價以上,每增加1都有對應的銷量,銷量大於0
第二步:列舉補貼,計算使得按照預期價格銷售的總利潤最大的第一個補貼值
第三步:列舉稅收,計算使得按照預期價格銷售的總利潤最大的第一個稅收值
第四步:輸出結果
100分程式碼:
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int t; //政府預期價
int s, ss; //成本價,成本價的銷量
int p[N]; //價格-銷量表,單價對應的銷量
int d; //最高單價外每升高一塊錢將減少的銷量
int main()
{
cin >> t >> s >> ss;
int x, y;
int lastx = s, lasty = ss; //上一個單價、銷量
int maxp; //最大單價
p[s] = ss;
while(cin >> x >> y)
{
if(x == -1 && y == -1) break;
maxp = max(maxp, x); //記錄最大單價
p[x] = y;
int change = (lasty - y) / (x - lastx); //計算單價lastx到x之間單價每增加1,銷量變化值
for(int i = lastx + 1, j = 1; i < x; i++, j++)
{
p[i] = lasty - change * j;
}
lastx = x, lasty = y;
}
cin >> d;
//補齊超出最大單價的銷量
for(int i = 1; p[maxp] - d * i > 0; i++)
{
p[maxp + i] = p[maxp] - d * i;
}
//列舉補貼,1~100000
int a = INT_MAX;
for(int bt = 1; bt <= 100000; bt++)
{
int yuqi = (t - s + bt) * p[t]; //政府預期價格的利潤
int maxs = 0; //最大利潤
for(int i = s; p[i] > 0; i++)
{
maxs = max(maxs, (i - s + bt) * p[i]);
}
if(yuqi == maxs)
{
a = bt;
break;
}
}
//列舉稅收,-1~-100000
int b = INT_MAX;
for(int tax = -1; tax >= -100000; tax--)
{
int yuqi = (t - s + tax) * p[t]; //政府預期價格的利潤
int maxs = 0; //最大利潤
for(int i = s; p[i] > 0; i++)
{
maxs = max(maxs, (i - s + tax) * p[i]);
}
if(yuqi == maxs)
{
b = tax;
break;
}
}
if(a == INT_MAX & b == INT_MAX) cout << "NO SOLUTION";
else
{
if(abs(a) < abs(b)) cout << a;
else cout << b;
}
return 0;
}