题目链接
题目梗概
正常的自由经济下,商品销量会随着价格的变动而变动,此时商家获得利润是和商品销量和价格有关的。
利润 = (价格 - 成本)* 销量( 这个函数是有关价格的复合函数。)
对于有些商品而言,不能放任市场随意定价,需要国家对商品价格进行控制。在这种情况下,国家会对这个商品规定一个价格,题中称为预期价格。商人在得到这个价格后,他必须要以这样的价格出售,并且根据市场规律获得对应的商品销量。但商人总是贪心的,他想要在规定价格及其对应销量下获得相比其他价格而言的最大收益。对于一般商品而言,价格和销量确定下后,是不是最大收益已经无法控制了。但对于这种管控商品而言,国家会对商家进行补贴或者收税,这种补贴或是收税,其实就是在价格和销量确定下后的价格再调整。此时,商人就可以通过这个手段调整价格来达到目的。
利润 = (预期价格 - 成本 + 调整价格)* 预期价格对应的销量
输入预期价格,多列商品价格及其对应的销量(第一列价格是商品成本价),(价格-销量)函数是由一段段的线段构成的分段函数,这些价格就是该函数的转折点。最后输入的数是分段函数最右端的线段的斜率(即输入的最高价后,每升高一元单价所减少的销量)。
输出能满足商人目的的调整价格,若有多种符合情况,输出绝对值最小的。
解题思路
从题意出发,商人要寻找预测价格下的能达到最大收益的调整价格,那就遍历调整价格,看哪个调整价格满足题意,该调整价格即为结果。
在确定的调整价格下,利润函数是有关价格和销量的变量的,同时销量又和价格是负相关的,他俩的函数关系虽然是分段的,但每段都是线性的,为方便起见,把销量和价格看成是线性相关的,此时,利润函数就是价格的二次函数,开口向下。对于二次函数而言,我们只需要让预测价格该点对应的利润值比它两次的利润值大,那它的利润就比其他价格时的利润都大。
上面提到,利润函数近似于二次函数,而对调整价格的加减就类似于对该函数进行左右平移(实际上会伴随上下移动)。那么,当我们增加调整价格时,是在对函数进行左移,函数的最高点也在左移,如果函数的最高点已经平移过了预测价格的点,那之后也就没有必要再进行左移了,此时就可以跳出遍历。减少调整价格时同理。
综上,我们首先通过输入的价格与销量对应表,找到预测价格及其对应的销量,预测价格-1及其对应的销量和预测价格+1及其对应的销量(这里根据数据的输入不同需要一些分类处理)。先递增遍历调整价格(即补贴),遇到符合题意的便退出遍历,或者达到左移边界也退出遍历。收税情况同理,比较补贴和收税两种结果的绝对值,取小者即为结果。
按照上述理解,通过函数平移一定能使最高点落在预测价格上,应该不存在没有解的情况。
完整代码
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
//打包物品价格与对应的销量
struct Pair{
int price, sales;
};
int main(){
//政府预期价
int expect;
cin >> expect;
vector<Pair> p;
Pair tmp;
int i = 0;
//在录入的价格中,处在政府预期价两边的最近的两个下标
int l = 0, r = 100000;
while(1){
cin >> tmp.price >> tmp