税收与补贴问题 \operatorname{税收与补贴问题} 税收与补贴问题
题目链接: luogu P1023 \operatorname{luogu\ P1023} luogu P1023
题目背景
每样商品的价格越低,其销量就会相应增大。现已知某种商品的成本及其在若干价位上的销量(产品不会低于成本销售),并假设相邻价位间销量的变化是线性的且在价格高于给定的最高价位后,销量以某固定数值递减。(我们假设价格及销售量都是整数)
对于某些特殊商品,不可能完全由市场去调节其价格。这时候就需要政府以税收或补贴的方式来控制。(所谓税收或补贴就是对于每个产品收取或给予生产厂家固定金额的货币)
题目
你是某家咨询公司的项目经理,现在你已经知道政府对某种商品的预期价格,以及在各种价位上的销售情况。要求你确定政府对此商品是应收税还是补贴的最少金额(也为整数),才能使商家在这样一种政府预期的价格上,获取相对其他价位上的最大总利润。
总利润=单位商品利润 $\times# 销量
单位商品利润 = = = 单位商品价格 − - − 单位商品成本 ( − - − 税金 or + + + 补贴)
输入
输入的第一行为政府对某种商品的预期价,第二行有两个整数,第一个整数为商品成本,第二个整数为以成本价销售时的销售量,以下若干行每行都有两个整数,第一个为某价位时的单价,第二个为此时的销量,以一行 − 1 -1 −1 , − 1 -1 −1 表示所有已知价位及对应的销量输入完毕,输入的最后一行为一个单独的整数表示在已知的最高单价外每升高一块钱将减少的销量。
输出
输出有两种情况:若在政府预期价上能得到最大总利润,则输出一个单独的整数,数的正负表示是补贴还是收税,数的大小表示补贴或收税的金额最小值。若有多解,取绝对值最小的输出。
如在政府预期价上不能得到最大总利润,则输出“NO SOLUTION”。
样例输入
31
28 130
30 120
31 110
-1 -1
15
样例输出
4
数据范围
所有数字均小于 100000 100000 100000
思路
这道题是一道可以直接暴力模拟的题目。
我
看
了
半
天
都
没
看
懂
题
意
,
还
是
看
题
解
才
知
道
它
到
底
在
B
B
什
么
{\color{white}我看了半天都没看懂题意,还是看题解才知道它到底在BB什么}
我看了半天都没看懂题意,还是看题解才知道它到底在BB什么
就是我们可以求出当单价为多少时的销量(因为其实就是几条连起来的直线),那我们其实就可以求出正常情况下单价为多少的时候利润最大(不是销量)。
如果刚好就是政府期望的,就直接输出。
如果比政府期望的小,就要收税;比政府期望的大,就要补贴。
(因为是收税和补贴都是按销量来看的,那补贴的话就要让销量大,收税就要让销量小)
那我们就一块一块地枚举收税或者补贴的钱,一直到刚好是政府期望的就结束。
至于不能打到政府期望的,这种情况应该有,但是 luogu 数据没有这种情况,所以。。。
不过应该就是如果后面枚举收税或者补贴的时候单价直接超过了,就是输出“NO SOLUTION”了把。。。
代码
#include<cstdio>
using namespace std;
int n, x, y, xx, yy, k[100001], mor, ben, num[100001], las, las_xie, las_num, ans, maxn;
bool fin;
int read() {
int an = 0, zhengfu = 1;
char c = getchar();
while(c < '0' || c > '9') {
if (c == '-') zhengfu = -zhengfu;
c = getchar();
}
while (c >= '0' && c <= '9') {
an = an * 10 + c - '0';
c = getchar();
}
return an * zhengfu;
}
int main() {
n = read();
ben = x = read();
y = read();
if (x == -1 && y == -1) fin = 1;
while (!fin) {
xx = x;
yy = y;
num[x] = y;//记录点对应的销量
x = read();
y = read();
if (x == -1 && y == -1) break;
k[xx] = (y - yy) / (x - xx);//求出直线的斜率
}
scanf("%d", &mor);
for (int i = ben; i <= xx; i++)
if (!num[i]) num[i] = (i - las) * las_xie + las_num;//求出每一个单价的销量
else {
las = i;
las_xie = k[i];
las_num = num[i];//记录这一个点的相关信息
}
while (yy - mor > 0) {//一直抬高单价知道销量变负或者0
xx++;
yy -= mor;
num[xx] = yy;
}
for (int i = ben; i <= xx; i++)//找到不管成本是多少收益最高
if (maxn < num[i] * (i - ben)) {
ans = i;
maxn = num[i] * (i - ben);
}
if (ans == n) {//不用调
printf("0");
return 0;
}
if (ans < n)//成本比预期小,收税
for (int i = -1; ; i--) {
maxn = 0;
for (int j = ben + 1; j <= xx; j++)
if ((j - ben + i) * num[j] >= maxn) {
ans = j;
maxn = (j - ben + i) * num[j];
}
if (ans == n) {
printf("%d", i);
return 0;
}
}
else {//成本比预期大,补贴
for (int i = 1; ; i++) {
maxn = 0;
for (int j = ben; j <= xx; j++)
if ((j - ben + i) * num[j] >= maxn) {
ans = j;
maxn = (j - ben + i) * num[j];
}
if (ans == n) {
printf("%d", i);
return 0;
}
}
}
return 0;
}