greedy策略求解工作选择问题Loss最小化(二)

         工作延时损失最小选择问题:每个工作包含工作耗时和延时损失2个属性,延时损失即该工作每延后一个小时开始做,则就损失一个loss值。注每个工作的耗时和延时损失各不相同。该问题类似于操作系统中的作业调度问题。

        因此若每个工作的loss值都相同,则等价于作业调度问题,即耗时短的应当最先做,即最短最优调度算法。该算法的原理的greedy策略点是time,即当前工作耗时越短,则后面工作的等待时间越少,则损失越少,最后累加的损失也是最小的;将耗时最大的排在前面先完成,则虽然越往后,后面的工作的损失的增量放缓,但由于前面的耗时过大,导致后面累加的延时基数很大,所以虽然增速放缓,但经累加后的延时仍然很大。相比于从小到大排序而言,耗时大的先做总的延时要大于耗时小的先做的总延时。所以在损失相同的情况下,总延时越小,则总的损失就越小,符合greedy=》min(loss)。

         另一方面,若每个工作的工作时间一定,则说明无论工作的先后顺序如何,总的延时都是一定的,则要想最后总的损失最小,则将损失大的工作优先做,则比将损失大的留在最后做的总损失要小。这里的greedy策略点是loss最小,符合最后greedy=》min(loss)。根据具体问题的条件选择greedy loss策略(即time、loss)。

        而本文问题的工作time 和loss是不定的,即任意数字。那么该问题的greedy策略点是什么呢?刚开始无从知晓,若仅从time 或loss其中之一来考虑,则仅能得到一个次优解,并不能得到最优解,所以必须将二者结合起来进行考虑,那么如何结合呢?二者相乘,相除或者其他的条件运算等等,一开始真不知道如何思考或者怎么下手,其实之所以有这种无从下手的困扰,本质上还是没有意识到greedy策略。没有在应用中去结合greedy策略方法,未能深入理解greedy策略点的,它到底是干嘛?那么如何在一个未知应用问题中知道去采用greedy方法呢?

       我最开始未能证明或想到greedy的策略点,因此直接查看了分析解答才知道以loss/time为greedy策略点进行求解。因此程序的核心是对所有工作按照其loss/time从大到小进行排序。下面是程序的主体框架如下:

std::vector<Point> GreedyStrategy::jobSequencingProblemLoss(vector<Point>num)
{
	//num[0].getId()==job_name,x==time,y==delay_loss
	mergeSortJobLoss(num,0,num.size()-1);                        //先对loss比进行greedy排序
	
	return num;
}

            因为只需要对loss/time进行排序即可,所以主体框架的程序调用排序算法如下:

void GreedyStrategy::mergeSortJobLoss(vector<Point>&num, int low, int high)     //若low!=high,则(low+high)/2=low,当low+1=high时;
{
	if (low<high)
	{
		int mid = (low + high) / 2;
		mergeSortJobLoss(num, low, mid);
		mergeSortJobLoss(num, mid + 1, high);
		conquerJobLoss(num, low, mid, high);
	}
}

void GreedyStrategy::conquerJobLoss(vector<Point>&num, int low, int mid, int high)
{
	int i = low;
	int j = mid + 1;
	vector<Point>numC;
	while (i<=mid&&j<=high)
	{
		if (num[i].getY()*num[j].getX()>=num[i].getX()*num[j].getY())
		{
			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];
	}
}

         总结:不管工作选择问题是什么,greedy的策略点首先应以最终所需要的结果或者到达的目的为greedy策略着眼点,如本文的最终目的是loss最小,那么不管你怎么想,并感觉无从下手时,remmber:最初的问题目的就是解题的greedy策略点(回到问题的起点)。既然是求得loss最小,那么最终的greedy首先的落脚点一定是loss,虽然题目中包含了time,那么在单位时间内,哪个工作的loss越大,则就应越先安排,即loss/time。这时会出现一个糊点:即loss/time真的就是最终的greedy策略点吗?根据remmber思路,最终得到的loss0 = loss/time得到的loss0首先是符合remmber策略的,而loss0的意义是单位时间的每个工作的损失,虽然时间是工作耗时,而并不是延时,那这个到底行不行呢?继续分析:loss0的看出来的意义是假设所有的工作都耗时单位时间(即一个单位时间),那么谁的损失越大,就应该优先做,因为在单位耗时中,损失越大,若越放在后面做,则总延时相等,但损失越大的后面做,则总的损失就越大,所以loss/time经反复论证得是正确的,得证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值