【蓝桥杯训练】背包问题
创始人
2025-05-30 23:18:33
0

1. 01背包问题

image-20221008212851875

1.1 版本1 二维

(1)状态f[i][j]定义:前 ii 个物品,背包容量 jj 下的最优解(最大价值):

当前的状态依赖于之前的状态,可以理解为从初始状态f[0][0] = 0开始决策,有 NN 件物品,则需要 NN 次决 策,每一次对第 ii 件物品的决策,状态f[i][j]不断由之前的状态更新而来。
(2)当前背包容量不够(j < v[i]),没得选,因此前 ii 个物品最优解即为前 i−1i−1 个物品最优解:

对应代码:f[i][j] = f[i - 1][j]。
(3)当前背包容量够,可以选,因此需要决策选与不选第 ii 个物品:

选:f[i][j] = f[i - 1][j - v[i]] + w[i]。
不选:f[i][j] = f[i - 1][j] 。
我们的决策是如何取到最大价值,因此以上两种情况取 max() 。

dp数组:所有包括第i个物品且体积不超过j的物品的集合。

核心思想,dp数组的分类处理,是否包含第i件物品,如果不包含

dp[i][j]=dp[i-1][j];

需要保证背包可以装下第i个物品

dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
import java.util.*;
public class Main{public static void main(String[] args){Scanner scan = new Scanner(System.in);int N = 1010;int[] v = new int[N];int[] w = new int[N];int[][] f = new int[N][N];int n = scan.nextInt();int m = scan.nextInt();for(int i = 1 ; i <= n ; i ++ ){v[i] = scan.nextInt();w[i] = scan.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])  f[i][j] = Math.max(f[i][j] , f[i - 1][j - v[i]] + w[i]);//右边包含i的方案,f[i-1][j - v[i]] + w[i]}}System.out.println(f[n][m]);}
}

1.2 版本2 一维

将状态f[i][j]优化到一维f[j],实际上只需要做一个等价变形。

为什么可以这样变形呢?我们定义的状态f[i][j]可以求得任意合法的i与j最优解,但题目只需要求得最终状态f[n][m],因此我们只需要一维的空间来更新状态。

(1)状态f[j]定义:NN 件物品,背包容量j下的最优解。

(2)注意枚举背包容量j必须从m开始。

(3)为什么一维情况下枚举背包容量需要逆序?在二维情况下,状态f[i][j]是由上一轮i - 1的状态得来的,f[i][j]与f[i - 1][j]是独立的。而优化到一维后,如果我们还是正序,则有f[较小体积]更新到f[较大体积],则有可能本应该用第i-1轮的状态却用的是第i轮的状态。

(4)例如,一维状态第i轮对体积为 33 的物品进行决策,则f[7]由f[4]更新而来,这里的f[4]正确应该是f[i - 1][4],但从小到大枚举j这里的f[4]在第i轮计算却变成了f[i][4]。当逆序枚举背包容量j时,我们求f[7]同样由f[4]更新,但由于是逆序,这里的f[4]还没有在第i轮计算,所以此时实际计算的f[4]仍然是f[i - 1][4]。

(5)简单来说,一维情况正序更新状态f[j]需要用到前面计算的状态已经被「污染」,逆序则不会有这样的问题。

状态转移方程为:f[j] = max(f[j], f[j - v[i]] + w[i] 。

import java.util.*;
public class Main{public static void main(String[] args){Scanner scan = new Scanner(System.in);int N = 1010;int[] v = new int[N];int[] w= new int[N];int[] f = new int[N];int n = scan.nextInt();int m = scan.nextInt();for(int i = 1;i<=n;i++){v[i] = scan.nextInt();w[i] = scan.nextInt();}for(int i = 1; i<=n;i++){for(int j = m;j>=0;j--){if(j >=v[i]) f[j] = Math.max(f[j],f[j-v[i]]+w[i]);}}System.out.println(f[m]);}
}

2. 完全背包问题

image-20221008221251420

思路:

同01背包问题。区别在于01背包对于每种物品只有选或不选,这也即「01」的由来。多重背包则对于每种物品可以多次选择。

2.1 二维朴素写法

import java.util.*;
public class Main{public static void main(String[] args){int N = 1010;int[] v= new int[N];int[] w =new int[N];int[][] f = new int[N][N];Scanner scan = new Scanner(System.in);int n = scan.nextInt();int m = scan.nextInt();for(int i = 1; i <= n ;i++){v[i] = scan.nextInt();w[i] = scan.nextInt();}for(int i = 1; i <=n;i++){for(int j = 0;j<=m;j++){f[i][j] = f[i-1][j];if(j >= v[i]) f[i][j] = Math.max(f[i][j],f[i][j-v[i]]+w[i]);}}System.out.println(f[n][m]);}
}

2.2 一维优化版

这里对比01背包问题,注意下标,我们可以发现

if(j >= v[i]) dp[i][j]=Math.max(dp[i][j],dp[i-1][j-v[i]]+w[i]);//01背包
if(j >= v[i]) f[i][j] = Math.max(f[i][j],f[i][j-v[i]]+w[i]);//完全背包

仅仅是f[i]dp[i-1]的区别,所以对应一维优化

import java.util.*;
public class Main{public static void main(String[] args){Scanner scan = new Scanner(System.in);int N = 1010;int[] v = new int[N];int[] w = new int[N];int[] f = new int[N];int n = scan.nextInt();int m = scan.nextInt();for(int i = 1 ; i <= n ; i ++ ){v[i] = scan.nextInt();w[i] = scan.nextInt();}for(int i = 1 ; i <= n ; i ++ ){for(int j = m ; j >= v[i] ; j -- ){f[j] = Math.max(f[j] , f[j - v[i]] + w[i]);}}}System.out.println(f[m]);}
}

3. 多重背包问题

image-20221108110733785

分析

当 si=1 时,相当于01背包中的一件物品
当 si>1 时,相当于01背包中的多个一件物品
故我们可以死拆(把多重背包拆成01背包)

直接枚举第i件物品的选择数,满足总体积不超过j即可

朴素解法

import java.util.*;
public class Main{public static void main(String[] args){Scanner scan = new Scanner(System.in);int N = 110;int[] v = new int[N],w = new int[N],s = new int[N];int[][] f = new int[N][N];int n = scan.nextInt();int m = scan.nextInt();for(int i = 1 ; i <= n ; i ++ ){v[i] = scan.nextInt();w[i] = scan.nextInt();s[i] = scan.nextInt();}for(int i = 1 ; i <= n ; i ++ )for(int j = 0 ; j <= m ; j ++ )for(int k = 0 ; k <= s[i] && k * v[i] <= j; k ++ )f[i][j] = Math.max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);System.out.println(f[n][m]);}
}

4. 分组背包问题

image-20221108110414313

分析:

image-20221108110457239

朴素解法

import java.util.*;
public class Main{public static void main(String[] ags){Scanner scan = new Scanner(System.in);int N = 110;int[][] v = new int[N][N];int[][] w = new int[N][N];int[] s = new int[N];int[] f = new int[N];int n = scan.nextInt();int m = scan.nextInt();for(int i = 1 ; i <= n ; i ++ ){s[i] = scan.nextInt();for(int j = 1 ; j <= s[i] ; j ++ ){v[i][j] = scan.nextInt();w[i][j] = scan.nextInt();}}for(int i = 1 ; i <= n ; i ++ ){for(int j = m ; j >= 0 ; j -- ){for(int k = 0; k <= s[i] ; k ++ ){if(j >= v[i][k])  f[j] = Math.max(f[j], f[j - v[i][k]] + w[i][k]);}}}System.out.println(f[m]);}
}
           for(int k = 0; k <= s[i] ; k ++ ){if(j >= v[i][k])  f[j] = Math.max(f[j], f[j - v[i][k]] + w[i][k]);}}}System.out.println(f[m]);
}

}


相关内容

热门资讯

走进小城看消费丨江西资溪:低碳...   夏日时节下午4点,江西省抚州市资溪县大觉山景区漂流终点依然热闹。来自南昌的游客余鑫漂流结束后没有...
【中原晨会0625】市场分析专... 来源:市场资讯 (来源:中原证券研究所) 本期重点研报目录 【中原策略】市场分析:电子半导体领涨 ...
南向资金连买4日!低费率+可月... 6月25日早盘,港股红利资产震荡整理。截至11时14分,港股红利低波ETF招商(520550)下跌0...
618成交破百万!紫荆花用一套... 一年一度的618年中大促,是消费市场的晴雨表,也是品牌间最激烈的角力场。当各大品牌在直播间里铆足了劲...
原创 黄... 2026年6月25日的国际金价已经从前期的5500美元高点跌到4200美元下方,累计跌幅超过22%,...
英伟达CEO:Vera Rub... 截至9:38,中证半导体材料设备主题指数(931743)涨2.36%创新高;权重股中,中微公司涨3....
再被催债16亿!“钢铁大王”戴... 澎湃新闻记者 贺梨萍 因“铁本事件”入狱五年的戴国芳重返钢铁行业,但他并没有完成从阶下囚再到“钢铁大...
周三原油价格下跌 随着美国和伊朗在和平谈判中取得进展,越来越多的油轮公开穿越霍尔木兹海峡,原油在战时的价格上涨已经蒸发...
这种蛋白是大脑衰老的开关 这种蛋白是大脑衰老的开关 清晨,假设一位五十岁左右的王女士发现自己常常把手机放在熟悉的抽屉里又找不到...
信通院牵头算力Token出海生... 盘面上,截至11:04,中证科创创业50指数(931643)涨1.68%,创历史新高;权重股中,芯原...
海外 774 亿营收背后:日本... 文 | 游戏价值论 6月23日,彭博社报道了腾讯正在围绕出售多家日本游戏工作室少数股权开展谈判,包...
餐饮“抢人”大战:把店开到公交... 作者 |餐饮老板内参 内参君 医院、公交站、演唱会…餐饮品牌,正在无孔不入 在北京儿童医院,肯德基...
快讯 | 外资扫货!陈翊庭:港... 港交所行政总裁陈翊庭在接受《中国证券报》专访时指出,国际资本对中国资产的看法已彻底扭转,布局中国市场...
2777.77元!A股“股王”... 25日早盘,昨天创下历史新高的A股“股王”联讯仪器,今天上午继续走强,盘中股价再度刷新历史新高。 截...
原创 今... 欧洲自己的媒体直接下结论,欧盟衰退躲不掉,内部分裂拦不住,现在就连欧洲顶尖工业巨头,都偷偷在用中国的...
黄仁勋股东大会放言:本轮AI基... 在当地时间6月24日的英伟达(NVDA.O)2026年度股东大会上,股东批准了该公司全部10名董事会...
国际油价大跌 新华社消息, 纽约原油期货主力合约价格24日盘中跌破每桶70美元,为伊朗战事爆发以来首次。 市场分析...
马云带队插秧,什么信号? 一场别开生面的“务农”,让外界看到了一个不一样的阿里巴巴。 近日,阿里巴巴合伙人、高德董事长刘振飞在...
全球最大产能,最高丰度达99.... 本文转自【科技日报】; 6月23日,高丰度硼-10同位素技术暨产业化成果发布会在山东省东营市举办,全...
黄金大跳水!金饰克价年内暴跌近... 25日,现货黄金盘中震荡,截至发稿,报3985.070美元/盎司,跌0.17%。 当地时间24日,...