传送门:http://poj.org/problem?id=2393
问题大意:给一个酸奶加工厂,一共N周 (1 <= N <= 10,000) ,每周生产酸奶的单价波动,为C_i (1 <= C_i <= 5,000),每周需要满足 Y_i (0 <= Y_i <= 10,000) 的订单量。每次的订单可由该周新生产的酸奶或之前就在仓库中的酸奶提供,计算满足所有订单所需的最少费用。有每周每单位酸奶存储费为s,总费用需要包括总生产成本+总存储费用。
本问题运用贪心算法,每次需要考虑下一次选择生产的周与本次需要生产周的生产量
当在第N个周时,假设N-1周的情况时最后一次生产实在N1周,N1-N-1中每周生产的单价
应该都大于C_N1+S*(周数-N1).在N月时只有两种可能1.选择在第N周生产2.选择在N1放到N
证明如果这两个都不选则要选择N1-N中间某个周N2进行生产,其生产价格应该为C_N2,
有其应该大于C_N1 + S * (N2 - N1),并且其后每周的价格都大于在N1月生产的价格。
即得证不可能在中间某周生产。
#include<iostream>
using namespace std;
int main()
{
int N, S;//总周份和每周存放单价
cin >> N >> S;
long long int TotalCost = 0;//N<=10,000,表示当只有前i周的情况时,所需总支出最低为;
int PreProduceWeek[10011] = { 0 };//表示当在只有前i周情况时,最后一次生产的周次;
int C[10011] = { 0 };//表示第i周时生产单价
int Y[10011] = { 0 };//表示每个月的订单数
int m = 1;
for (int i = N; i > 0; i--)
{
cin >> C[m] >> Y[m];
m++;
}
TotalCost=Y[1]*C[1];
PreProduceWeek[1] = 1;
for (int i = 2; i <= N; i++)
//计算前i个月时的最低总支出
{
int tmpWeek = PreProduceWeek[i - 1];
//cout << "tmpWeek=" << tmpWeek << endl;
if (C[i] > (C[tmpWeek] + S * (i - tmpWeek)))
//情况1,当当前月不买适合
{
PreProduceWeek[i] = PreProduceWeek[i - 1];
TotalCost+= (C[tmpWeek] + S * (i - tmpWeek))*Y[i];
}
else
{
TotalCost+= C[i] * Y[i];
PreProduceWeek[i] = i;
}
}
cout << TotalCost;
return 0;
}
需要注意的两个点是
1.poj的output中有提示:the minimum total cost to satisfy the yogurt schedule. Note that the total might be too large for a 32-bit integer.
此时输出用int类型就不行了,poj会报为wrong answer的错误。
2.(1 <= N <= 10,000) 的数组定义需要大小需要10011否则会出现Runtime error。暂时没想明白为什么,可能是越界吧,希望有大神解答。
看了一眼其他人的代码发现还有自己的代码还有很大优化空间。
上述代码中记录到每周的最后一次生产价格其实是为了记录最便宜价格,与C[i]进行比较。由于i+1周价格最终单价只可能是C[i]+s或者C[i],其实并不需要知道i周参照的到底是哪个单价,只需要记住C[i]最终的单价就可以了。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int N, S;//总周份和每周存放单价
cin >> N >> S;
long long int TotalCost = 0;//N<=10,000,表示当只有前i周的情况时,所需总支出最低为;
int C[10011] = { 0 };//表示第i周时生产单价
int Y[10011] = { 0 };//表示每个月的订单数
int m = 1;
for (int i = N; i > 0; i--)
{
cin >> C[m] >> Y[m];
m++;
}
TotalCost = Y[1] * C[1];
for (int i = 2; i <= N; i++)
//计算前i个月时的最低总支出
{
C[i] = min(C[i],C[i-1]+S);
TotalCost += C[i] * Y[i];
}
cout << TotalCost;
return 0;
}
还算一道相对简单的贪心问题了。