题目描述
实现一个算法求解 01 背包问题。背包问题的介绍如下:
- 已知一个容量为 totalweight 的背包,有不同重量不同价值的物品,问怎样在背包容量限制下达到利益最大化。
- 01 背包问题要求每个物品只有一个,可以选择放入或者不放入背包。
背包问题求解方法的介绍如下:
- 用符号 Vi 表示第 i 个物品的价值,Wi 表示第 i 个物品的体积,Vi,j 表示当前背包容量为 j 时,前 i 个物品最佳组合对应的价值。
- 对于当前第 i 个商品,如果包的容量比该物品体积小,即 j<Wi。那么此时的价值与前 i−1 个的价值是一样的,即 Vi,j=Vi−1,j。
- 对于当前第 i 个商品,如果包的容量能够装下该物品,即 Wi≤j。此时需要判断装或者不装这个物品的价值对比,选择使价值更大的情况,即 Vi,j=max(Vi+Vi−1,j−Wi,Vi−1,j)。
通过最优解回溯法找到解的组成:
- 当 Vi,j=Vi−1,j时,说明没有选择第 i 个物品。
- 当 Vi,j=Vi−1,j−Wi 时,说明装了第 i 个商品。
- 从 i,j 的最大值一直遍历到 i=0 ,则找到了所有解。
输入描述
第一行为两个数字 totalweight、N,均不超过 1000。totalweight 含义见题干,N 为物品数量。
接下来 N 行,每行两个数字Wi、Vi,均不超过 1000。含义见题干。
输出描述
输出一行,为在背包容量限制下的最大化利益。
输入输出样例
示例
输入
8 5
3 4
5 5
1 2
2 1
2 3
输出
10
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int bagweigth = scan.nextInt();
int num = scan.nextInt();
int[][] sum = new int[num][bagweigth+1];
int[] weigth = new int[num];
int[] value = new int[num];
for(int i = 0; i < num; i++){
weigth[i] = scan.nextInt();
value[i] = scan.nextInt();
}
sun(sum,weigth,value,bagweigth,num);
System.out.println(sum[num - 1][bagweigth]);
scan.close();
}
public static void sun(int[][] sum, int[] weigth, int[] value, int bagweigth, int num){
for(int i = 0; i < bagweigth + 1; i++){
if(i < weigth[0]){
sum[0][i] = 0;
}else{
sum[0][i] = value[0];
}
}
for(int i = 0; i < num; i++){
sum[i][0] = 0;
}
for(int i = 1; i < num; i++){
for(int j = 1; j < bagweigth + 1; j++){
if(j < weigth[i]){
sum[i][j] = sum[i - 1][j];
}else{
sum[i][j] = Math.max(sum[i - 1][j],sum[i - 1][j - weigth[i]]+ value[i]);
}
}
}
}
}