Acwing---2.背包问题(0-1背包)+优化

1.题目

在这里插入图片描述

2.基本思想

  • 状态 f[i][j] 定义:前 i 个物品,背包容量 j下的最优解(最大价值):
    当前的状态依赖于之前的状态,可以理解为从初始状态 f[0][0] = 0 开始决策,有 N件物品,则需要 N 次决 策,每一次对第 i件物品的决策,状态 f[i][j] 不断由之前的状态更新而来。
    1. f[i][0]=f[0][j]=0 //第一行第一列为0
    1. j < v[i],(当前背包容量不够没得选),因此前 i个物品最优解即为前 i−1个物品最优解:​ &nbsp: 即:f[i][j] = f[i - 1][j]
    1. j >= v[i]背包容量够可以选,因此需要决定选与不选第 i个物品:
      ​ 选:f[i][j] = f[i - 1][j - v[i]] + w[i]。不选:f[i][j] = f[i - 1][j]

3. 代码实现

二维DP

public class _2背包问题_01背包 {
    /*
     * dp[i][j] 表示为前i个物品j重量的最大价值
     * ① 当v[i]>j 剩下容量放不进去 直接继承 前i-1件的最大价值 dp[i][j]=dp[i-1][j]
     * ② 当v[i]<=j 有两种选择 当前物品放进去和不放进去
     * 		③放进去  dp[i][j]=dp[i-1][j-v[i]]+w[i];
     * 		④不放进去 dp[i][j]=dp[i-1][j]
     */
   public static void main(String[] args) {
       //输入
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();
        int V= sc.nextInt();
        int []v=new int[N+1];//体积
        int []w=new int[N+1];//价值
        for (int i = 1; i <=N ; i++) {
            v[i]=sc.nextInt();
            w[i]=sc.nextInt();
        }

        int [][]dp=new int[N+1][V+1];
        for (int i = 1; i <=N ; i++) {
            for (int j = 0; j <=V; j++) {
                if (j>=v[i])
                    //  当前背包容量能装进第i个物品,则价值选和不选去Max值
                    dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
                else
                    //  当前背包容量装不进第i个物品,则价值等于前i-1个物品
                    dp[i][j]=dp[i-1][j];
            }
        }
        System.out.println(dp[N][V]);
    }
}

空间优化一维DP

public class _2背包问题__01背包_优化成一维数组 {
	public static void main(String[] args) {
		/*
		 * (1) 如果不装第 i 件物品,那么问题就转化为“前 i−1 件物品放入容量为 j的背包中的最大价值”
		   (2) 如果装第 i件物品,那么问题就转化为“前 i−1 件物品放入剩下的容量为 j−v[i] 的背包中的最大价值”
		 */
		Scanner sc = new Scanner(System.in);
		int N=sc.nextInt();
		int V=sc.nextInt();
		int[] v=new int[N+1]; //体积
		int[] w=new int[N+1]; //价值
		
		for(int i=1;i<=N;i++) {
			v[i]=sc.nextInt();
			w[i]=sc.nextInt();
		}
		
		int[] dp=new int[V+1];
		dp[0]=0;
		for(int i=1;i<=N;i++) {
			//采取逆序的方式
			//假如枚举到:i = 3, j = 8, v[3] = 5, w[3] = 1
			//二维:dp[3][8] = max(dp[2][8], dp[2][3] + w[3])   此时的dp[2][8]和dp[2][3]都是上一轮的状态值
			//一维:dp[8] = max(dp[8], dp[3] + w[3])      我们要保证dp[8]和dp[3]都是上一轮的状态值
			//按照逆序的顺序,一维dp数组的更新顺序为:dp[8], dp[7], dp[6], ... , dp[3]
			//如果按照顺序进行更新,dp[3] = max(dp[3], dp[0] + w[0]),对dp[3]的状态进行了更新,
			//那么在更新dp[8]时,用到的dp[3]就不是上一轮的状态了,不满足动态规划的要求。
			for(int j=V;j>=v[i];j--) {
				dp[j]=Math.max(dp[j], dp[j-v[i]]+w[i]);
			}
		}
		System.out.println(dp[V]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

amant 柒少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值