簡體   English   中英

如何在0-1背包中獲取所選物品的清單?

[英]How to get the list of selected items in 0-1 knapsack?

我有一個背包問題天真的解決方案的代碼,我想獲取所選項目的索引列表,目前它返回所選項目的值的總和。 任何幫助將不勝感激。 JAVA代碼:

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
/* A Naive recursive implementation of 0-1 Knapsack problem */
class Knapsack
{

    // A utility function that returns maximum of two integers

     static int max(int a, int b) {

        return (a > b)? a : b; }

     // Returns the maximum value that can be put in a knapsack of capacity W
     static int knapSack(float W, float wt[], int val[], int n)
     {
        // Base Case

    if (n == 0 || W == 0)
        return 0;

    // If weight of the nth item is more than Knapsack capacity W, then
    // this item cannot be included in the optimal solution
    if (wt[n-1] > W)
      {

        return knapSack(W, wt, val, n-1);
      }
    // Return the maximum of two cases: 
    // (1) nth item included 
    // (2) not included
    else { 
        return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
                     knapSack(W, wt, val, n-1)
                      );
    }            
      }


   // Driver program to test above function
   public static void main(String args[])
   {
        int val[] = new int[]{29,74,16,55,52,75,74,35,78};
        float wt[] = new float[]{85.31f,14.55f,3.98f,26.24f,63.69f,76.25f,60.02f,93.18f,89.95f};
    float  W = 75f;
    int n = val.length;
    System.out.println(knapSack(W, wt, val, n));
    }
}

當前結果:148預期結果:2.7

這是您的操作方法(盡管它使用了一些額外的內存)-

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
/* A Naive recursive implementation of 0-1 Knapsack problem */
class Knapsack
{

    // A utility function that returns maximum of two integers

     static int max(int a, int b) {

        return (a > b)? a : b; }

     // Returns the maximum value that can be put in a knapsack of capacity W
     static int knapSack(float W, float wt[], int val[], int n,int visited[])
     {
        // Base Case

    if (n == 0 || W == 0)
        return 0;

    // If weight of the nth item is more than Knapsack capacity W, then
    // this item cannot be included in the optimal solution
    if (wt[n-1] > W)
      {

        return knapSack(W, wt, val, n-1,visited);
      }
    // Return the maximum of two cases: 
    // (1) nth item included 
    // (2) not included
    else {

        int v1[]=new int[visited.length];
        System.arraycopy(visited, 0, v1, 0, v1.length);
        int v2[]=new int[visited.length];
        System.arraycopy(visited, 0, v2, 0, v2.length);
        v1[n-1]=1;

        int ans1 = val[n-1] + knapSack(W-wt[n-1], wt, val, n-1,v1);
        int ans2 = knapSack(W, wt, val, n-1,v2);
        if(ans1>ans2){
            System.arraycopy(v1, 0, visited, 0, v1.length);
            return ans1;
        }
        else{
            System.arraycopy(v2, 0, visited, 0, v2.length);
            return ans2;
        }
    }            
      }


   // Driver program to test above function
   public static void main(String args[])
   {
        int val[] = new int[]{29,74,16,55,52,75,74,35,78};
        float wt[] = new float[]{85.31f,14.55f,3.98f,26.24f,63.69f,76.25f,60.02f,93.18f,89.95f};
    float  W = 75f;
    int n = val.length;
    int visited[] = new int[n];
    System.out.println(knapSack(W, wt, val, n, visited));
    for(int i=0;i<n;i++)
        if(visited[i]==1)
            System.out.println(i+1);
    }
}

我所做的是,我創建了一個訪問數組,如果使用當前元素,則比我將當前元素標記為“訪問”,否則它保持為零。 最后,我遍歷此數組並打印訪問量為1的每個元素

即使公認的解決方案可以滿足需要,但我認為它還是有一些缺陷。 基本上,我們可以使用一種技巧來提高時間效率,並跟蹤選定的項目。

背包問題可以通過動態編程解決,這意味着我們需要緩存中間結果,並使用它們進行較少的計算。 請注意,可接受的代碼不存儲中間結果,這意味着某些組合的計算不止一次。 這是很好的描述: geeksforgeeks 回到您的問題(因為geekforgeeks上的文章沒有告訴您如何還原所選項目):

我們可以使用緩存數組來還原選定的項目:我們從最后一個元素開始,因為我們的緩存是2d數組,所以這是

var r = K.length -1
car c = K(0).length -1 
var curr = K(r)(c)

現在,雖然我們沒有到達第一行(因為輔助行,所以我們不檢查第一行),但是我們將當前值與上一行(同一列)中的值進行比較。 如果它們相同,則意味着我們沒有使用相應的項目,因此我們僅轉到(r-1)行。 如果它們不同-使用了該項,我們將同時更新行和列。

// here I use same names as in the geekforgeeks article 
// val - array of values
// K - cache for intermediate results, 
// wt - array of weights

    i = K.length - 1
    j = W
    while (i > 0) {
      k = K(i)(j)
      if (k != K(i - 1)(j)) {
        println("selected item: val(i - 1)")
        j -= wt(i - 1)
      }
      i -= 1
    }

我在這里找到了這種方法: cs.cmu.edu

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM