题目连接:http://poj.org/problem?id=2393
题目大意:
酸奶工厂需要生产酸奶,共N周。同时,酸奶每周单位重量的价格Price不一样,且每周的需求量needs也不同,但是可以存储酸奶(一周生产多周的酸奶)且不考虑腐败的情况,存储酸奶的价格是每周每单位重量酸奶需花费S,即本周生产的酸奶多于本周的需求,则需要花钱存储起来。问:最低成本是多少?
题目分析:
题目有这么几点需要提到:
1. 生产能力无上限
2. 存储酸奶的能力无上限
3. 每周的酸奶需求都必须满足,即第i周需要x单位的酸奶,那么在第1到i周的时间内必须生产出x单位的酸奶。
解决问题的核心是贪心的思路。如何贪心?出发点应该是第i周的酸奶应该在第1到i周的哪一周生产。这一点很重要,因为不同的选择决定了第i周酸奶的单位价格(该价格越小,第i周的成本越低)。而且从题目可以看出,N总共生产的酸奶应该等于N周的总需求,所以有如下公式:
成本= need_1*lowprice_1 + need_2*lowprice_2 + ...........+ need_N*lowprice_N (1)
公式里的lowprice_i代表为满足该周需求酸奶的最低生产价格,它由直接生产价格(Price)和保存价格(S)决定,公式如下:
lowprice_i = min(lowprice_1, lowprice_2, ........., lowprice_i) (2)
其中,lowprice_i显然就是第i周的直接生产价格price_i(不要保存哈),但是前面i-1周的价格需要知道。
这里没必要每次都重复计算,那样的话算法的时间复杂度等于O(N^2)。其实,公式(2)可以简化为下式:
lowprice_i = min(lowprice_i-1 + S, lowprice_i) (3)
其中,第i-1周的最低价格加保存S的原因是多出来一周(第i周),那么当然需要保存。
基于上面的贪心方法,时间复杂度等于O(N),C++代码如下:
注意题目的数据范围,N周的最低成本应该用long long类型表示,对应的printf输出格式选择%lld
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N_MAX = 10000;
int price[N_MAX], needs[N_MAX];
int s, N;
long long res;
void init(){
res = 0;
scanf("%d%d", &N, &s);
for(int i = 0; i < N ; i++){
scanf("%d%d", &price[i], &needs[i]);
}
return ;
}
void solve(){
int lowprice = price[0];
res += lowprice*needs[0];
for(int i = 1; i < N; i++){
lowprice = min( lowprice+s, price[i]);
res += lowprice*needs[i];
}
return ;
}
int main()
{
init();
solve();
printf("%lld\n", res);
return 0;
}
虽然题目很水,但也是理解之后觉得水。不会之前都说,会了就不难。总之,出发点很重要,如果该题从一周应该生产未来哪些周的酸奶出发,那么问题将变得很难理解和复杂(一开始是这么想的)。虽然开始绕弯,但是在弯路里发现了一些规律,对走回正道有帮助。所以,不怕走弯路,只要边走边思考,一定能回到正轨。殊途同归哈!