CSP歷年複賽題-P1023 [NOIP2000 普及組] 稅收與補貼問題

江城伍月發表於2024-05-21

原題連結: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;
}

相關文章