0-1背包问题

作者: 故梦_三笙 | 来源:发表于2019-05-06 09:00 被阅读2次

0-1背包问题

给n个重量为w1,w2,w3,...,wn,且价值为v1,v2,v3,...vn的物品和容量为C的背包,每个东西只能选择用一次或者不用(这就是0-1的由来),求这个物品的一个最有价值的子集,使得在满足背包容量的前提下,包内价值最大。

动态规划解决

我们定义dp[i][j]为在有i个物品且背包容量为j的前提下,包内最大的价值;
那么则有
1 不放第i个物品时,dp[i][j]=dp[i-1][j]
2 放第i个物品时,dp[i][j]=dp[i-1][j-w[i]]+v[i]
所以状态转移方程就是dp[i][j]=max(dp[i-1][j],dp[i][j]=dp[i-1][j-w[i]]+v[i])

public class KnapSack01 {
    public static int knapSack(int[] w, int[] v, int C) {
        int size = w.length;
        if (size == 0) {
            return 0;
        }

        int[][] dp = new int[size][C + 1];
        //不放物品时显然价值为0
        for (int i = 0; i <= C; i++) {
            dp[0][i] = 0;
        }
        //背包容量为0时价值也为0
        for(int i=0;i<=size;i++)
            dp[i][0]=0;
        //填充其他行和列
        for (int i = 1; i < size; i++) {
            for (int j = 0; j <= C; j++) {
                dp[i][j] = dp[i - 1][j];
                if (w[i] <= j) {
                    dp[i][j] = Math.max(dp[i][j], v[i] + dp[i - 1][j - w[i]]);
                }
            }
        }
        return dp[size - 1][C];
    }

    public static void main(String[] args) {
        int[] w = {2, 1, 3, 2};
        int[] v = {12, 10, 20, 15};
        System.out.println(knapSack(w, v, 5));
    }
}

根据上述代码,时间复杂度为O(sizeC),这已经是最快的了,无法再简化,但是空间复杂度O(sizeC)可以在简化,这里我们使用了二维数组,因此接下来使用一维数组存储
这里我们定义dp[i]为容量为i时的最大价值,则有推导
dp[i]=dp[i-1] 不放下一个物品
dp[i]=dp[i-w[j]]+v[j] 放下一个物品
所以状态转移方程就是dp[i]=max(dp[i-1],dp[i-w[j]]+v[j]).


public class KnapSack01 {
    public static int knapSack(int[] w, int[] v, int C) {
        int size = w.length;
        if (size == 0) {
            return 0;
        }

        int[] dp = new int[C + 1];
        //初始化所有价值都为0,其实只要保证是一个很小的数就行
        for (int i = 0; i <= C; i++) {
            dp[i] =0;
        }

        for (int i = 1; i < size; i++) {
            for (int j = C; j >= w[i]; j--) {
                dp[j] = Math.max(dp[j], v[i] + dp[j - w[i]]);
            }
        }
        return dp[C];
    }

    public static void main(String[] args) {
        int[] w = {2, 1, 3, 2};
        int[] v = {12, 10, 20, 15};
        System.out.println(knapSack(w, v, 5));
    }
}

这样空间复杂度就是O(C)了。
说这么多,来看真题
![E(0EZK9QZ@RNL3(XCBGPL7.png
这道题可以理解为每张邮票的价值都是1,现在要求一个最佳子集使得邮票的价值最小也就是邮票的数量最小,显然是0-1背包问题,下面是代码

#include <stdio.h>

int main()
{
    int weight[21];
    int f[101];
    int m,n,i,j;
    while(scanf("%d",&m)!=EOF)
    {
        scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&weight[i]);
    f[0]=0;
        //初始化
        for(i=1;i<=m;i++)
            f[i]=1000000;
    for(i=1;i<=n;i++)
    {
        for(j=m;j>=weight[i];j--)
        {
             f[j]=f[j]<f[j-weight[i]]+1?f[j]:f[j-weight[i]]+1;
        }
    }  
    if(f[m]>0&&f[m]<=n)
        printf("%d",f[m]);
        else
            printf("0");
    }
    return 0;
}

恩,今天就到这里,下次有时间看一下其他背包问题,这个0-1背包也要继续练习。
但行好事,莫问前程!

相关文章

  • 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/oxsloqtx.html