算法交流 超市问题 【基本算【题目描述】 超市 By Oler87wa
超市里有N件商品,每个商品都有利润pi和过期时间di,每天只能卖一件商品,过期商品(即当天di<=0)不能再卖。
求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。【输入格式】
输入包含多组测试用例,测试用例最多30组。
每组测试用例,以输入整数N开始,接下里输入N对pi和di,分别代表第i件商品的利润和过期时间。
在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。【输出格式】
对于每组产品,输出一个该组的最大收益值。
每个结果占一行。 【样例输入】
4 50 2 10 1 20 2 30 1
7 3 1 2 1 10 3 100 2 8 2 1 20 50 10 【样例输出】
80
169【测试数据范围】
对于20%数据,0≤N≤100
对于60%数据,0≤N≤1000
对于100%数据,0≤N≤10000
1≤pi,di≤10000 一.题意分析.
这道题可以用贪心算法解决,具体算法是建立大根堆,在这个数组中,存在一个比较的过程,对于过期天数相同的商品,价值高的商品将会覆盖价值低的商品,比较过程结束后,对于每个过期天数,将只剩下一个商品,在最后将这些商品的价值相加即是最终所求的最大价值.二.算法说明三.数据结构
scanf("%d",&i);//i指商品件数
for(k=0;k<i;k++)
{
scanf("%d%d",&c,&d);//通过循环输入c和d
循环结构输入,i指商品件数,c指商品价值,d指商品的过期时间.四.算法分析
先构建一个最大收益函数,用来计算最大收益.在该函数中,定义一个一维整形数组(10000个且全部置为零)过期时间设为数组下标,然后通过循环结构输入商品件数,对应价值和过期时间,然后通过比较结构,对于同一天过期的商品,取价值最大的那个.当全部输入完成过后,将数组中剩下全部不为零的元素进行相加,得到的结果即是最大价值.五.代码与调试
#include<stdio.h>//思想:建立大根堆
void good()//构造计算最大收益函数
{
int i,j,k,c,d,t,num=0,a[10001]={0};//c指价值,d指过期剩余的时间 ,数组a的初始值全部设为0
scanf("%d",&i);//i指商品件数
for(k=0;k<i;k++)
{
scanf("%d%d",&c,&d);//通过循环输入c和d
for(j=d;j>0;j--)
{
if(c>a[j])
{
t=c;c=a[j];a[j]=t;//如果输入的价值大于该位置之前的价值,则将他替换
}
if(a[j]==0)
break;//如果比较到0的位置,则结束循环,减少循环次数
}
}
for(j=0;j<10001;j++)
{
num=num+a[j];//通过循环将数组中的值相加
}
printf("%dn",num);//输出最后的最大收益
}
int main()
{
int x,n;//n指的是数据的组数
scanf("%d",&n);
for(x=0;x<n;x++)
{
good();//调用good函数
}
return 0;
}六.总结
这个算法我也是想了两天,没有一点头绪,最后向大佬求助,在他们的帮助下才给解出来的.总的来说,这些题对新手来说还是很不友好的,一开始我根本就没有想到可以用大根堆的方法来做(上个学期学的数据结构都还给老师了),结果大神一点拨,才知道如此简单,只用十多分钟就编出来了.总的来说,这是一个循序渐进的过程,做的多,一熟悉,就不会再浪费那么多时间.相信自己会慢慢爱上算法.算法改变世界!
这个算法还是存在一些缺点,比如时间复杂度太大,这么个程序编译时间长达十秒!我觉得这是因为循还相加得到最大价值那一步还需要一步一步加,要加一万次,导致时间复杂度太高,解决办法可以只对那些大于零的元素进行相加,但个人目前还没有想到优化方法,欢迎各路大佬指教!