税收与补贴问题
题目背景
每样商品的价格越低,其销量就会相应增大。现已知某种商品的成本及其在若干价位上的销量(产品不会低于成本销售),并假设相邻价位间销量的变化是线性的且在价格高于给定的最高价位后,销量以某固定数值递减。(我们假设价格及销售量都是整数)
对于某些特殊商品,不可能完全由市场去调节其价格。这时候就需要政府以税收或补贴的方式来控制。(所谓税收或补贴就是对于每个产品收取或给予生产厂家固定金额的货币)
题目描述
你是某家咨询公司的项目经理,现在你已经知道政府对某种商品的预期价格,以及在各种价位上的销售情况。要求你确定政府对此商品是应收税还是补贴的最少金额(也为整数),才能使商家在这样一种政府预期的价格上,获取相对其他价位上的最大总利润。
总利润=单位商品利润 \times× 销量
单位商品利润=单位商品价格 - 单位商品成本 (- 税金 or + 补贴)
输入输出格式
输入格式:
输入的第一行为政府对某种商品的预期价,第二行有两个整数,第一个整数为商品成本,第二个整数为以成本价销售时的销售量,以下若干行每行都有两个整数,第一个为某价位时的单价,第二个为此时的销量,以一行-1−1,-1−1表示所有已知价位及对应的销量输入完毕,输入的最后一行为一个单独的整数表示在已知的最高单价外每升高一块钱将减少的销量。
输出格式:
输出有两种情况:若在政府预期价上能得到最大总利润,则输出一个单独的整数,数的正负表示是补贴还是收税,数的大小表示补贴或收税的金额最小值。若有多解,取绝对值最小的输出。
如在政府预期价上不能得到最大总利润,则输出“NO SOLUTION”。
输入输出样例
输入样例#1:
31 28 130 30 120 31 110 -1 -1 15
输出样例#1:
4
说实话题目我就没看懂,还是看讨论组的解释.....题目解释
数据比较水只有四组数据。。。。。
解题方法有两种:
1、首先把所有可能的价格和销售列举出来,然后依次解方程,再在区间内求出答案
2、首先把所有可能的价格和销售列举出来,暴力枚举可能的补贴,保证预期价格获得的利润最优,发现解救跳出循环。
我选择第一种
看懂题目后就可以慢慢来解放程了,我们需要让在预期的时候利润大于等于其他价格的利润
(预期价格-成本+补贴)*预期的销售 >= (其他价格-成本+补贴)*其他价格的销售
把所有的方程解出,找到满足所有解的区间,最靠近0的那个端点就是解。
最后输出的时候需要注意,如果那个点是正数需要向上取整(使用函数ceil(x),返回double型,在math.h里面),是负数向下取整(使用函数floor(x),返回double型)。
其他注释看代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
#define Max 100005
#define max(a,b) a>b?a:b;
#define min(a,b) a>b?b:a;
/*只有四组数据??
总结下各个题解的思路:
1、首先把所有可能的价格和销售列举出来,然后依次解方程,再在区间内求出答案
2、首先把所有可能的价格和销售列举出来,暴力枚举可能的答案,保证预期价格获得的利润最优
我选择第二种
*/
using namespace std;
int a[Max];//价格,销售数量
double left=-999999,right=999999;//左区间和右区间
int main()
{
int want_price;//预期价格
int cost_price,cost_sale;//成本价
int max_price,max_cost; //记录最高的价格
int m,n,p,q;//给出的价格,临时使用的变量
scanf("%d%d%d",&want_price,&cost_price,&cost_sale);
a[cost_price]=cost_sale;//把成本和销售保存
p=cost_price,q=cost_sale;
/*本来以为需要排序,然后发现题目给的顺序就是从小到大....*/
while(scanf("%d%d",&m,&n)&&m!=-1&&n!=-1)//都不等于-1 ,
{
int cha=(n-q)/(m-p);//每块钱的差额
for(int i=p+1;i<=m;i++)
{
a[i]=q+cha*(i-p);
}
p=m,q=n;
}
scanf("%d",&m); //最高价开始减少
max_price=p; //最高价格
max_cost=q; //最高价格的销售
while(1)
{
max_price++;//自增
max_cost-=m;//自减
if(max_cost>0) //销售量不能小于0
a[max_price]=max_cost;
else
{
max_price--; //最后一个价格去掉
break;
}
}
int want_profit=(want_price-cost_price)*a[want_price];//预期的利润*销量
for(int i=cost_price;i<=max_price;i++)//依次解方程
{
if(i==want_price) continue; //自己不用比
double x=(i-cost_price)*a[i]-want_profit;
if(a[want_price]-a[i]<0) //系数小于0
{
x=x/(a[want_price]-a[i]);
if(x<right) //需要满足所有区间,所有发现最小的右区间,则选择
{
right=x;
}
}
else if(a[want_price]-a[i]>0) // 系数大于0
{
x=x/(a[want_price]-a[i]);
if(x>left)//发现最大的左区间,则选择
{
left=x;
}
}
else
{
continue;
}
}
/*其实就是看区间内哪个点离0最近*/
if(left>0) printf("%d \n",int(ceil(left))); //大于0的情况需要向上取整
else if(right<0) printf("%d \n",int(floor(right))); //小于0的情况需要向下取整
else printf("0\n"); //答案在中间,选择0
return 0;
}
emmm,这个题目看了很多次,每次都没写,然后有次考试遇到了,心态炸了......