【问题标题】:Knapsack 0-1 path reconstruction (which items to take) [duplicate]背包0-1路径重建(要带哪些物品)[重复]
【发布时间】:2011-06-23 13:27:06
【问题描述】:

我知道如何使用动态编程方法解决背包 0-1 问题,但是在不影响 O(N * C)(N 个项目,C 容量)的复杂性的情况下确定要拿哪些物品时遇到了麻烦。

有什么想法(我更喜欢自下而上的方法)?

【问题讨论】:

    标签: algorithm path dynamic-programming knapsack-problem bottom-up


    【解决方案1】:

    假设,现在您将结果存储在数组 bool[] a 中,其中当 sum i 可以达到时,a[i] 为真。
    您将需要另一个数组int[] b,其中b[i] 是您放入背包以求和i 的最后一个元素。

    那么,你在哪里

    a[i] = true;
    

    你需要

    a[i] = true;
    b[i] = current_item;
    

    那么,找出哪些项可以取到 sum i 就是一个简单的循环。

    PS 为简单起见我使用了两个数组,但显然数组a 可以去掉。

    【讨论】:

    • 我实际上对如何重建感兴趣(即打印获得最大值的项目)。我想出了时间复杂度为O(N * C) 但使用 O(N * C) 空间的解决方案。我不认为只用一两个数组就可以重建。
    • @leden 这正是这种方法的作用,只有一个数组。哪部分描述不清楚?
    • @Nikita Rybak:您能否进一步详细说明您的解决方案?谢谢!
    • @axel22 您需要哪个部分的信息,构建b 或使用它重新创建解决方案?
    • 如何使用b 重新创建解决方案?
    【解决方案2】:

    这里是在 O(n) 时间内重建路径的修改

    int knapsack(int weight[], int profit[], int no_of_items, int capacity) {
        for (int var = 0; var <= capacity; ++var) {
            dp[0][var] = 0;
        }
        for (int var = 0; var <= no_of_items; ++var) {
            path[var] = false;
        }
        int using_item_i, without_using_item_i;
        for (int i = 1; i <= no_of_items; ++i) {
            for (int j = 1; j <= capacity; ++j) {
                without_using_item_i = dp[i - 1][j];
                using_item_i = 0;
                if ((weight[i]) <= j) {
                    using_item_i = dp[i - 1][j - weight[i]] + profit[i];
                }
    
                if (using_item_i >= without_using_item_i) {
                    taken[i][j] = true;
                    dp[i][j] = using_item_i;
                } else {
                    taken[i][j] = false;
                    dp[i][j] = without_using_item_i;
                }
            }
        }
        //Reconstructing back the path
        int j = capacity;
        for (int i = no_of_items; i >= 0; --i) {
            if (taken[i][j]) {
                path[i] = true;
                cnt++;
            }
            j = j -  weight[i];
        }
        return dp[no_of_items][capacity];
    }
    

    【讨论】:

      【解决方案3】:
      boolean[] solution = new boolean[nItems];
      
      for (int i = nItems, c = maxCapacity; i > 0 && c > 0; i--) {
          int iThItemAddedValue = value[i - 1][c - weights[i - 1]] + values[i - 1];
          int iThItemInheritedValue = value[i - 1][c];
      
          if (iThItemAddedValue > iThItemInheritedValue) {
              solution[i - 1] = true;
              c = c - weights[i - 1];
          } else {
              solution[i - 1] = false;
          }
      }
      

      【讨论】:

        【解决方案4】:

        查看附图中的溶胶

        【讨论】:

        • 打印“tmpList”数组,它会打印路径
        • edit您的帖子并将实际代码显示为文本而不是屏幕截图。其他人无法从您的图像中复制和粘贴。 See here 了解详情。谢谢。
        【解决方案5】:
        public class Knapsackproblem {
            private static int[][] cache;
            public static void main(String[] args) {
                int val[] = new int[]{60, 100, 120};
                int wt[] = new int[]{10, 20, 30};
                int  W = 50;
                int n = val.length;
                System.out.println(knapSack(W, wt, val, n));
                printValues(wt,val);
            }
        
            /**
             * This method will find the result with
             * more value with weight less than or equal
             * to given weight
             * @param w given weight
             * @param wt arrays of weights
             * @param val array of values
             * @param n length of the array
             * @return max value we can obtain
             */
            private static int knapSack(int w, int[] wt, int[] val, int n) {
            cache = new int[n+1][w+1];
                for (int i = 1; i <= n; i++) {
                    for (int j = 1; j <= w; j++) {
                        if(j < wt[i-1]){
                            cache[i][j] = cache[i-1][j];
                        }else {
                            cache[i][j] = Math.max(cache[i-1][j],(cache[i-1][j-wt[i-1]])+val[i-1]);
                        }
                    }
                }
                for (int[] aCache : cache) {
                    System.out.println(Arrays.toString(aCache));
                }
                return cache[n][w];
            }
        
            private static void printValues(int[] wt, int[] val) {
                int m = cache.length-1;
                int n = cache[0].length-1;
                util(wt,val,m,n);
            }
        
            private static void util(int[] wt, int[] val, int m, int n) {
                if(m <=0 || n<=0) return;
                if((cache[m][n] != cache[m-1][n]) && (cache[m][n] != cache[m][n-1])){
                    System.out.println(val[m-1]+"-->"+wt[m-1]);
                    util(wt, val, m-1, (n - wt[m - 1] + 1));
                }else
                if(cache[m][n] == cache[m-1][n]){
                    util(wt,val,m-1,n);
                }
                else if(cache[m][n] == cache[m][n-1])
                    util(wt,val,m,n-1);
                else
                    util(wt,val,m,(n-val[m-1]+1));
            }
        }
        

        【讨论】:

          【解决方案6】:

          【讨论】:

          • 答案中的链接已失效。
          猜你喜欢
          • 2016-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-02-10
          • 1970-01-01
          相关资源
          最近更新 更多