题目
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
8
问题解决:
(1)将题中输入举例转换成表格,清晰表现,后续计算帮助理解:
(2)总体思路:
动态规划
用子问题定义状态:即 f[i][v] 表示前 i 件物品恰放入一个容量为 v 的背包可以获得的最大价值。
则其状态转移方程便是:
(3)01背包问题特点:每件物品仅有一件,选择放或不放
则该问题的子问题:前 i 件物品放入容量为 V 的背包中,考虑第 i 件物品放或不放。
每件物品只有两种状态:放与不放,而在前i件物品中已经选择好放那些物品,然后考虑第 i 件放或不放是否会有当前最大价值即最优解。
-
不放第i件物品:
两种情况:1.背包剩余容积不足以装下第i件物品:则此时的价值与前i-1个物品价值一样: f[i][v] = f[i-1][v];
2.有足够的容积,但是装了第i件不一定会达到当前最大价值,因此要在装与不装之间作比较,选较大者:f[i][v] = max ( f[i-1][v],f[i][v-c[i]]+w[i] );若结果是 f[i-1][v] 则不放第i件物品。 -
放第i件物品:
有足够的背包空间,并且选择放之后有当前最大价值,但同样直接作比较得出计算结果:f[i][v] = max ( f[i-1][v],f[i][v-c[i]]+w[i] );
(4)根据状态转移方程可以将题中数据代入计算填表,进一步理解: -
1.初始化:f[0][0] = 0;
-
2.代入数据进行计算验证,如:
i=1,j=1,w[1] = 2,v[1] = 1,j = v[1],f[1][1]= max ([f[1-1][1] , f[1-1][1-1]+2) ) = 2;
一行一行的填表,得出结果,如下图 :
得到最大价值为:f[N][V] = 8.
代码实现:
1.基本思路:
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner read1 = new Scanner(System.in);
int N = read1.<