洛谷P1023 税收与补贴问题(模拟)
题目背景
每样商品的价格越低,其销量就会相应增大。现已知某种商品的成本及其在若干价位上的销量(产品不会低于成本销售),并假设相邻价位间销量的变化是线性的且在价格高于给定的最高价位后,销量以某固定数值递减。(我们假设价格及销售量都是整数)
对于某些特殊商品,不可能完全由市场去调节其价格。这时候就需要政府以税收或补贴的方式来控制。(所谓税收或补贴就是对于每个产品收取或给予生产厂家固定金额的货币)
题目描述
你是某家咨询公司的项目经理,现在你已经知道政府对某种商品的预期价格,以及在各种价位上的销售情况。要求你确定政府对此商品是应收税还是补贴的最少金额(也为整数),才能使商家在这样一种政府预期的价格上,获取相对其他价位上的最大总利润。
总利润=单位商品利润 \times× 销量
单位商品利润=单位商品价格 - 单位商品成本 (- 税金 or + 补贴)
输入输出格式
输入格式:
输入的第一行为政府对某种商品的预期价,第二行有两个整数,第一个整数为商品成本,第二个整数为以成本价销售时的销售量,以下若干行每行都有两个整数,第一个为某价位时的单价,第二个为此时的销量,以一行-1−1,-1−1表示所有已知价位及对应的销量输入完毕,输入的最后一行为一个单独的整数表示在已知的最高单价外每升高一块钱将减少的销量。
输出格式:
输出有两种情况:若在政府预期价上能得到最大总利润,则输出一个单独的整数,数的正负表示是补贴还是收税,数的大小表示补贴或收税的金额最小值。若有多解,取绝对值最小的输出。
如在政府预期价上不能得到最大总利润,则输出“NO SOLUTION”。
输入输出样例
输入样例#1:
31
28 130
30 120
31 110
-1 -1
15
输出样例#1:
4
说明
所有数字均小于100000
题解:
首先我们知道,价钱与销量是反相关的,而且销量是价钱的线性函数,所以收益应为一个二次函数,所以最大值的点应为题中所给的预期价,则只需让价格比它小1(设为l)和大1(设为r)的利润都小于它即可满足在预期价处利润最大。
则我们需要l和r处的销量。
题中给出所有数字小于100000,我们可以直接暴力算出每个大于成本价的值,这样如果预期值小于最大值,则可以直接求出,若大于,分类讨论一下也很简单。
之后我们可以暴力循环,直接找使预期值为最大利润的税收或补贴。
分>0和<0两种情况讨论,取绝对值最小。
代码;
#include<bits/stdc++.h>
#define maxn 100050
using namespace std;
int a[maxn];
int x[maxn], y[maxn];
int cmp(int x, int y) {
return x > y;
}
int main() {
int exp1;
scanf("%d", &exp1);
scanf("%d%d", &x[1], &y[1]);
a[x[1]] = y[1];
int maxx = 0;
int n = 2;
int a1, b;
while (scanf("%d%d", &a1, &b)) {
if (a1 == -1 && b == -1) break;
x[n] = a1; y[n] = b;
n++;
}
sort(x + 1, x + n);
sort(y + 1, y + n, cmp);
for (int i = 2; i <= n; i++) {
for (int j = x[i - 1] + 1; j <= x[i]; j++) {
a[j] = a[j - 1] - (y[i - 1] - y[i]) / (x[i] - x[i - 1]);
}
}
int change;
scanf("%d", &change);
int l, m, r;
if (exp1 >= x[n - 1]) {
m = y[n - 1] - (exp1 - x[n - 1]) * change;
l = y[n - 1] - (exp1 - x[n - 1] - 1) * change;
r = y[n - 1] - (exp1 - x[n - 1] + 1) * change;
}
else {
m = a[exp1];
l = a[exp1 - 1];
r = a[exp1 + 1];
}
int ans = maxn;
for (int i = 0; i <= maxn; i++) {
int ansl = (exp1 - 1 - x[1] + i) * l;
int ansm = (exp1 - x[1] + i) * m;
int ansr = (exp1 - x[1] + i + 1) * r;
if (ansm >= ansl && ansm >= ansr) {
ans = i;
break;
}
}
for (int i = 0; i >= -maxn; i--) {
int ansl = (exp1 - 1 - x[1] + i) * l;
int ansm = (exp1 - x[1] + i) * m;
int ansr = (exp1 - x[1] + i + 1) * r;
if (ansm >= ansl && ansm >= ansr) {
if (abs(i) < ans) {
ans = i;
}
break;
}
}
cout << ans;
return 0;
}