该问题求解的是货物谁先生产的问题,由于生产完成的货物存在保质期,已完成的货物每存放一天,货物就会以一个固定的比例decay重量。且每个货物的生产时间都为一天。在所有货物生产完时,求解最终货物的最大重量。
由于是求解货物重量的最大化,所以该问题本身是一个优化问题,问题的最终目的是得到一个最优解,因此是否能够用greedy优化策略:既然是寻找最后剩余的最大货物质量,那么基于greedy思想,只有每天当前货物的损失最小,就能使最终的货物总重量达到最大。
由于每过一天货物V都会以比例P损失,而质量越大的货物在同等损失比例下,损失的越多,所以先做质量较小的货物,最后做质量较大的货物,比如最后一个质量最大的货物完成时,就不用存放,不需decay,所以总的损失最小。
因此,在实现中,问题被简化成了将货物按照重量从小到大进行排序的问题,那么为什么问题最后的实现求解是对货物重量按照从小到大排序呢?是如何找到求解实现该问题的方法呢?其实在对问题进行阅读和分析的过程中,从求解问题的最终目的(最小损失《=》最大剩余总重量)出发,重量越大的物品每放置一天,则以同等比例decay下,其损失越大,所以损失越大的物品越留在后面做,则decay天数越少,则总的损失就越小。那么是不是这样呢?即greedy策略点是不是得到最优解呢?
本文Greedy策略点是当前decay损失最小,且已完成的货物每天的decay损失最小化。
本文程序的核心实现是对所有货物的质量进行从小到大的排序,其主体框架程序如下:
double GreedyStrategy::goodsLossMin(vector<double>num)
{
double sum_value;
double result=0;
mergeSortGoods(num, 0, num.size() - 1);
int t = num.size()-1;
int day;
for (int i = 0; i < num.size();i++)
{
day = t - i; //这里的decay有两种方法:time 和spaces//先以time计算
result += computerSurplus(num[i], day, 0.2); //递归中开辟内存的时间与直接用for的时间的比较???
}
return result;
}
上面采用了一个归并排序函数对货物重量进行排序,然后调用了一个计算decay损失剩余函数对已排序的物品进行decay计算,这两个函数的实现如下:
void GreedyStrategy::mergeSortGoods(vector<double>&num, int low, int high)
{
if (low<high)
{
int mid = (low + high) / 2;
mergeSortGoods(num, low, mid);
mergeSortGoods(num, mid + 1, high);
conquerGoods(num, low, mid, high);
}
}
void GreedyStrategy::conquerGoods(vector<double>&num, int low, int mid, int high)
{
int i = low;
int j = mid + 1;
vector<double>numC;
while (i <= mid&&j <= high)
{
if (num[i]<num[j])
{
numC.push_back(num[i]); //由小到大进行排序
i++;
}
else
{
numC.push_back(num[j]);
j++;
}
}
while (i<=mid)
{
numC.push_back(num[i]); //由小到大进行排序
i++;
}
while (j<=high)
{
numC.push_back(num[j]);
j++;
}
for (int i = low, k = 0; i <= high, k < numC.size(); i++, k++)
{
num[i] = numC[k];
}
}
double GreedyStrategy::computerSurplus(double volume, int day,double rate)
{
while (day)
{
volume = volume - volume*rate;
day--;
}
return volume;
}
总结:根据问题的最终目的进行分析,寻找求解问题的高效算法,若是寻找最优解,则可根据求解目标寻找greedy策略点。
来源:CSDN
作者:tanshemeng9736
链接:https://blog.csdn.net/tanshemeng9736/article/details/103705453