📜  工作选择问题–损失最小化策略|套装2

📅  最后修改于: 2021-04-24 20:00:33             🧑  作者: Mango

之前,我们已经讨论了一种最小化损失的策略:作业排序问题–最小化损失。在本文中,我们将研究适用于稍有不同的问题的另一种策略。
我们给了N个生产商品的序列,编号从1到N。每个商品的体积都由(Vi)表示。约束条件是,商品一旦完成,其体积便开始以每天固定的百分比(P)衰减。所有商品以相同的速度腐烂,并且每种商品需要一天的时间才能完成。
我们被要求找到生产货物的顺序,以使货物的总体积最大化。
示例1:

Input: 4, 2, 151, 15, 1, 52, 12 and P = 10%
Output: 222.503

解决方案:在最佳作业顺序中,所有作业结束时剩余的总货物量为222.503
示例2:

Input: 3, 1, 41, 52, 15, 4, 1, 63, 12 and P = 20%
Output: 145.742

解决方案:在最佳作业顺序中,所有作业结束时剩余的总货物量为145.72

解释 –
由于这是一个优化问题,我们可以尝试使用贪婪算法来解决此问题。每天,我们都会从尚待生产的商品中进行选择。因此,我们所需要的只是一个局部选择标准或启发式方法,当将其应用于选择工作时,将为我们提供最佳结果。
除了尝试使音量最大化之外,我们还可以尝试使损失最小化。由于可以从所有商品获得的总体积也是恒定的,因此,如果我们使损失最小化,则可以保证获得最佳答案。
现在考虑音量V有什么好处
第一天后的损失:PV
第2天后损失:PV + P(1-P)V或V(2P-P ^ 2)
第3天后损失:V(2P-P ^ 2)+ P(1 – 2P + P ^ 2)V或V(3P – 3P ^ 2 + P ^ 3)
随着天的增加,损失也增加。因此,诀窍是确保生产后不使货物闲置。此外,由于要求我们每天至少生产一份工作,因此我们应该执行小批量工作,然后再执行大批量工作。此策略有效的原因有两个。

  1. 大批量货物生产后不会闲置。
  2. 随着数量的减少,每天的损失也会减少,因此对于小批量商品,损失在几天后就可以忽略不计了。

因此,为了获得最佳解决方案,我们稍后会生产更大数量的商品。对于第一天,选择数量最少的商品并生产它。从商品清单中删除生产的商品。对于第二天,重复相同的步骤。剩下的商品要生产时,请不断重复。
计算生产结束时的总体积时,请记住在第i天将产生

(1-P)^{N-i}

乘以剩余的音量。显然,自第N天(最后一天)产生的货物的体积将保持不变,因为

(1-P)^{N-N} = 1

算法 –

Step 1: Add all the goods to a min-heap       
Step 2: Repeat following steps while Queue is not empty
        Extract the good  at the head of the heap
        Print the good
        Remove the good from the heap
        [END OF LOOP]
Step 4: End

复杂性–
我们恰好执行了N个push()和pop()操作,每个操作都需要花费log(N)时间。因此,时间复杂度为O(N * log(N))。
下面是该解决方案的实现。

C++
// C++ implementation of the
// above approach
#include 
using namespace std;
 
void optimum_sequence_jobs(vector& V, double P)
{
    int j = 1, N = V.size() - 1;
    double result = 0;
 
    // Create a min-heap (priority queue)
    priority_queue, greater > Queue;
 
    // Add all goods to the Queue
    for (int i = 1; i <= N; i++)
        Queue.push(V[i]);   
 
    // Pop Goods from Queue as long as it is not empty
    while (!Queue.empty()) {
 
        // Print the good
        cout << Queue.top() << " ";
 
        // Add the Queue to the vector
        // so that total voulme can be calculated
        V[j++] = Queue.top();
        Queue.pop();
    }
 
    // Calclulating volume of goods left when all
    // are produced. Move from right to left of
    // sequence multiplying each volume by
    // increasing powers of 1 - P starting from 0
    for (int i = N; i >= 1; i--)
        result += pow((1 - P), N - i) * V[i];   
 
    // Print result
    cout << endl << result << endl;
}
 
// Driver code
int main()
{
    // For implementation simplicity days are numbered
    // from 1 to N. Hence 1 based indexing is used
    vector V{ -1, 3, 5, 4, 1, 2, 7, 6, 8, 9, 10 };
 
    // 10% loss per day
    double P = 0.10;
 
    optimum_sequence_jobs(V, P);
 
    return 0;
}


Java
// Java implementation of the
// above approach
import java.util.*;
class GFG{
 
  static void optimum_sequence_jobs(int[] V,
                                    double P)
{
    int j = 1, N = V.length - 1;
    double result = 0;
 
    // Create a min-heap
    // (priority queue)
    PriorityQueue Queue =
                  new PriorityQueue<>();
 
    // Add all goods to the Queue
    for (int i = 1; i <= N; i++)
      Queue.add(V[i]);   
 
    // Pop Goods from Queue as
    // long as it is not empty
    while (!Queue.isEmpty())
    {
      // Print the good
      System.out.print(Queue.peek() +
                       " ");
 
      // Add the Queue to the vector
      // so that total voulme can
      // be calculated
      V[j++] = Queue.peek();
      Queue.remove();
    }
 
    // Calclulating volume of goods
    // left when all are produced.
    // Move from right to left of
    // sequence multiplying each
    // volume by increasing powers
    // of 1 - P starting from 0
    for (int i = N; i >= 1; i--)
      result += Math.pow((1 - P),
                          N - i) * V[i];   
 
    // Print result
    System.out.printf("\n%.2f\n",
                      result );
  }
 
// Driver code
public static void main(String[] args)
{
  // For implementation simplicity
  // days are numbered from 1 to N.
  // Hence 1 based indexing is used
  int[] V = {-1, 3, 5, 4, 1,
             2, 7, 6, 8, 9, 10};
 
  // 10% loss per day
  double P = 0.10;
 
  optimum_sequence_jobs(V, P);
}
}
 
// This code is contributed by Amit Katiyar


输出 –

1 2 3 4 5 6 7 8 9 10 
41.3811