美文网首页
0-1背包问题

0-1背包问题

作者: 我不吃甜食 | 来源:发表于2019-01-09 19:25 被阅读0次

条件:
有若干个物品,重量分别为w1, w2, w3 .....wi, 将这些物品装入一个最大承受重量为capacity的袋子中,求最大能装入的重量。

我们试着用回溯算法解决这个问题,回溯算法其实就是一个一个的试,将所有情况都试一遍,最终找到满足条件的那个值。

实现如下:

int[] elements = {3, 1, 5, 2, 4}  //物品重量
int capacity=9; //袋子容量
int cw = 0; //当前袋子的重量
int max = 0; //
for (int i = 0; i < elements.length; i++) {//从第一个元素开始,遍历所有可能性
       f(i, elements[i]);
}
//
void f(int i, int cw) {
        if (cw == capacity || i == elements.length - 1) {
            if (cw > max) {
                max = cw;
            }
            return;
        }
        f(i + 1, cw);//下一个不放
        int cw2 = cw + elements[i + 1];
        if (cw2 <= capacity) {
            f(i+1, cw2); //下一个放
        }
}

f(i, cw)表示从第i个元素开始放入去寻找满足条件的最大重量,cw表示当前袋子已放入的重量,每运行完一次f(i,cw),总能确定一个max。对于上述例子,总体上运行5次f(i, cw)就能确定最大的max。

如下图表示,其中红色节点表示下一个物品不放入袋中,此时cw不变,max也不变;绿色表示下一个物品放入袋中。对于给定的i和cw,f(i, cw)总能计算出一个max(=到现在为止最大的那个cw)。黄色节点即为满足条件的节点。

从第一个元素开始放入的所有可能性

从上图可以看出,当放入第1,4,5或第1,2,3个元素时满足条件;


从第二个元素开始放入的所有可能性

从这个图可以看出,当从第二个元素开始放入时,放入第2,3,4时可以使重量最大。

从上面两个图中我们也可以发现,在计算f(0,3)和f(1,1)时出现了很多相同的中间状态,比如f(4,5)、f(4,8)等,若把这些中间状态保存起来,后面使用时就不必再计算了,这样肯定能提高效率。
优化f(i, cw):

int[][] his = new int[elements.length][capacity+1];//数组默认值都为0
void f(int i, int cw) {
        if(his[i][cw] > 0) {//当前参数条件下,max已计算过,不用再计算了
            return;
        } else {
            his[i][cw] = 1; //留下痕迹,标识计算过f(i, cw)
        }
        if (cw == capacity || i == elements.length - 1) {
            if (cw > max) {
                max = cw;
            }
            return;
        }
        f(i + 1, cw);//下一个不放
        int cw2 = cw + elements[i + 1];
        if (cw2 <= capacity) {
            f(i+1, cw2); //下一个放
        }
}

二维数组中的值并没有实际意义,因此可以用boolean类型代替,减少内存占用

boolean[][] his = new boolean[elements.length][capacity+1];//数组默认值都为0
void f(int i, int cw) {
        if(his[i][cw]) {//当前参数条件下,max已计算过,不用再计算了
            return;
        } else {
            his[i][cw] = true; //留下痕迹,标识计算过f(i, cw)
        }
        if (cw == capacity || i == elements.length - 1) {
            if (cw > max) {
                max = cw;
            }
            return;
        }
        f(i + 1, cw);//下一个不放
        int cw2 = cw + elements[i + 1];
        if (cw2 <= capacity) {
            f(i+1, cw2); //下一个放
        }
}

相关文章

  • Algorithm进阶计划 -- 动态规划(下)

    经典动态规划背包问题最长子序列问题 1. 背包问题 1.1 0-1 背包问题 0-1 背包问题,描述如下: 上面...

  • 背包问题

    背包问题属于典型的动态规划问题。这里我们将详细介绍0-1背包,完全背包和多重背包问题 一、 0-1背包 有N件物品...

  • 算法-动态规划-背包问题

    背包问题是基础的动态规划问题,包含了0-1背包,完全背包,多重背包等。 0-1背包 存在容量为 的背包 , 件体...

  • 背包问题

    1、前言 背包问题是典型的动态规划问题,它有非常多的类型,本文讨论最常见的0-1背包问题 0-1背包问题描述:有一...

  • (python实现)购物单问题

    购物单问题实际上是0-1问题,在解决这个问题之前,要理解0-1背包问题。可以自己百度或者阅读我对0-1背包问题的理...

  • 动态规划

    0-1背包问题 自己实现的0-1背包问题的动态规划解法,先贴上吧,动态规划原理解释有空再写。

  • 动态规划常见面试题

    子序列类型编辑距离 最长递增子序列 最大子数组 最长公共子序列 背包问题0-1背包问题 子集背包问题 完全背包问题...

  • 编程

    今天用0-1算法,编写了背包问题!

  • LeetCode 动态规划专题 5:0-1 背包问题

    这一节我们介绍使用动态规划解决的一个非常经典的问题:0-1 背包问题。 0-1 背包问题描述 问题描述: 有一个背...

  • 数据结构与算法笔记day23:动态规划

    1初识动态规划 这节课的内容不涉及动态规划的理论,而是通过两个例子:0-1背包问题、0-1背包问题升级...

网友评论

      本文标题:0-1背包问题

      本文链接:https://www.haomeiwen.com/subject/nmvwrqtx.html