贪婪算法:首先是最高值与最早的截止日期

时间:2015-06-22 00:50:53

标签: algorithm language-agnostic job-scheduling greedy

假设我们要执行一组n个作业,每个作业需要一个单位时间。在任何时候我们都可以完成一项工作。作业i1<=i<=n只有在截止日期之前执行,才能为我们赢利。

如果至少有一个序列允许在不超过截止日期的时间内执行集合中的每个作业,那么我们可以完成一组作业。 &#34;最早的截止日期&#34;是可行的。

显示贪婪算法是最优的:如果所选择的一组作业仍然可行,则在每个步骤中添加尚未考虑的具有最高利润值的作业。

必须首先执行:首先显示始终可以重新安排两个可行序列(一个由Greedy计算),以便同时安排两个序列共有的每个作业。这个新序列可能包含间隙。

更新

我创建了一个似乎反驳算法的例子:

假设有4个职位:

  • 工作A有利润1,持续时间2,第3天之前的截止日期;
  • 工作B的利润为4,持续时间为1,截止日期为第4天;
  • 工作C的利润为3,持续时间为1,截止日期为第3天;
  • 工作D的利润为2,持续时间为1,第2天为截止日期。

如果我们首先使用最高利润的贪婪算法,那么我们只得到工作B&amp; C.但是,如果我们先做截止日期,那么我们可以获得所有工作,而且订单是CDB

不确定我是否以正确的方式接近这个问题,因为我创建了一个例子来反驳问题所需要的

3 个答案:

答案 0 :(得分:1)

事实上,最早的截止日期不是第一个&#34;,&#34;最高的利润第一&#34;也不是&#34;最高的利润/持续时间&#34;是正确的算法...

假设2个职位:

  • 工作A的利润为1,持续时间为1,截止日期为第1天;
  • 工作B有利润2,持续时间2,第2天之前的截止日期;

然后&#34;最早的截止日期&#34;未能得到正确的答案。正确答案是B。

假设另外5个工作:

  • 工作A有利润2,持续时间3,截止日期为第3天;
  • 工作B的利润为1,持续时间为1,截止日期为第1天;
  • 工作C的利润为1,持续时间为1,第2天为截止日期;
  • 工作D的利润为1,持续时间为1,截止日期为第3天;
  • 工作E的利润为1,持续时间为1,截止日期为第4天;

然后&#34;最高利润第一&#34;未能得到正确的答案。正确答案是BCDE。

假设另外4个工作:

  • 工作A有利润6,持续时间4,第6天截止日期;
  • 工作B有利润4,持续时间3,第6天之前的截止日期;
  • 工作C有利润4,持续时间3,第6天之前的截止日期;
  • 工作D的利润为0.0001,持续时间为2,第6天的截止日期为

然后&#34;最高利润/持续时间第一&#34;未能得到正确的答案。正确答案是BC(感谢@ dognose&#39的反例,见评论)。

一种正确的算法是动态编程:

按截止日期递增的第一个订单。 dp[i][j] = k表示在第一个i个职位中,在j个时间单位内,我们可以获得k最高利润。然后是dp[0][0] = 0

工作信息存储在3个数组中:利润存储在profit[i], 1<=i<=n,持续时间存储在time[i], 1<=i<=n,截止日期存储在deadline[i], 1<=i<=n

  // sort by deadline in ascending order
  ...
  // initially 2 dimension dp array are all -1, -1 means this condition unreachable
  ...
  dp[0][0] = 0;
  int maxDeadline = max(deadline); // max value of deadline
  for(int i=0;i<n;i++) {
      for(int j=0;j<=maxDeadline;j++) {
          // if do task i+1 satisfy deadline condition, try to update condition for "within the first i+1 jobs, cost j+time[i+1] time units, what's the highest total profit will be"
          if(dp[i][j] != -1 && j + time[i+1] <= deadline[i+1]) {
              dp[i+1][j+time[i+1]] = max(dp[i+1][j+time[i+1]], dp[i][j] + profit[i+1]);
          }
      }
  }
  // the max total profit can get is max value of 2 dimension dp array

DP算法的时间/空间复杂度(n*mn是作业计数,m是最大期限)高度依赖于作业数量和最大期限。如果n和/或m相当大,可能很难得到答案,而对于常见用途,它会很好用。

答案 1 :(得分:0)

此问题看起来像作业车间调度,这是NP完全的(这意味着没有最佳的贪婪算法 - 尽管专家们试图找到一个自70&#39; S)。 Here's a video在该用例的更高级形式上,使用Greedy算法然后进行本地搜索来解决。

如果我们假设您的用例确实可以放宽到Job Shop Scheduling,那么有许多优化算法可以提供帮助,例如Metaheuristics(包括禁忌搜索和模拟退火等本地搜索),(M)IP,动态编程,约束编程,...有这么多选择的原因是因为没有一个是完美的。我更喜欢Metaheuristics,因为他们在我所见过的所有研究挑战中超出了其他人。

答案 2 :(得分:0)

这个问题称为有期限的作业排序,可以通过两种基于贪婪策略的算法来解决:

  1. 排序输入作业会减少利润。对于每个工作,将其放入解决方案的工作清单中,这些清单在截止日期之前越来越多。如果包括工作之后解决方案中的某些工作的索引比截止日期要好,请不要包括该工作。
  2. 排序输入作业会减少利润。对于每个作业,将其放在最后可能的索引上的解决方案作业列表中。如果没有免费索引小于或等于工作截止日期,则不要包括该工作。