背包九讲

背包九讲

01背包

有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。

第 ii 件物品的体积是 vivi,价值是 wiwi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000

输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:

8

二维数组 

import java.util.*;

public class Main {
    //   f[i][j]  
    // 1.不选第i个物品 f[i][j]=f[i-1][j]
    // 2.选第i个物品  f[i][j]=f[i-1][j-v[i]]
    // f[0][0]=0;
    // f[i][j]=max(1,2);
    public static void main(String[] args) {
       Scanner in=new Scanner(System.in);
       int N=1010;
       int f[][]=new int[N][N];//前i个物品体积为j的时候的最大价值
       int v[]=new int[N];//体积
       int w[]=new int[N];//价值
       int n=in.nextInt();//数量
       int m=in.nextInt();//体积
       for(int i=1;i<=n;i++){
           v[i]=in.nextInt();
           w[i]=in.nextInt();
       }
       for(int i=1;i<=n;i++){
           for(int j=0;j<=m;j++){
               f[i][j]=f[i-1][j];//不选第i个物品
               if(j>=v[i])//选第i个物品
               f[i][j]=Math.max(f[i][j],f[i-1][j-v[i]]+w[i]);
           }
       }
       System.out.println(f[n][m]);
       
    }
}

 一维数组

import java.util.*;

public class Main {
    static final int N=1010;
    public static void main(String args[]){
     Scanner in=new Scanner(System.in);   
     int n=in.nextInt();
     int m=in.nextInt();
     int v[]=new int[N];
     int w[]=new int[N];
     int dp[]=new int[N];
     for(int i=1;i<=n;i++){
         v[i]=in.nextInt();
         w[i]=in.nextInt();
     }
     /*将二维数组压缩成一维数组不断更新
     dp[j]从最大容量开始更新,否则会将上一次循环的给更新掉
     j前边的部分就是二维数组前i-1个的结果
     所以从后边开始更新就不会影响结果
如果使用顺序,会先更新f[4],再更新f[7],对于这个书包问题来讲,
就是有可能,在更新f[4]的时候,已经把这次能加的物品加进来了,
然后更新f[7]的时候,还有可能再加一次,所以必须使用逆序,
保证,f[4]是没有加入新物品前,背包里的最优解。
     */
     for(int i=1;i<=n;i++){
         for(int j=m;j>=v[i];j--){
            //  if(j>=v[i])可以优化到循环内部
             dp[j]=Math.max(dp[j],dp[j-v[i]]+w[i]);
         }
     }
     System.out.println(dp[m]);
    }
}

初始化情况

f[0]  的初始值是0 其余都是负无穷(正好装满的时候最大值)

除0外初始化为负无穷,那么仅刚好装下的位置是正数(从0加),其余位置为负数(从负无穷加)

求恰好装满的最大价值,需要枚举一遍。

f[]  的初始值都是0(<=m时的最大值)

 完全背包问题

有 NN 种物品和一个容量是 VV 的背包,每种物品都有无限件可用。

第 ii 种物品的体积是 vivi,价值是 wiwi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 种物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000

输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
10

 完全背包和01背包的唯一区别就是一个物品可以用无限次

初始化跟01背包一样

import java.util.*;
public class Main{
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值