import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
/**
* 有n个物品,第i(1<=i<=n)个物品的价值为Vi,重量为Wi,背包容量为sackWeight,考虑<b>如何选择装入背包的物品</b>,
* 使得装入背包的物品的<b>总价值最大</b>。
* 选择放入物品到背包,此时记作 Xi = 1,否则记 Xi = 0;则经过若干选择后形成行向量(X1, X2, X3, X4, ...Xi, ...)
* 假设放入第i个物品,放入后达到总价值最大,
* C[i,j]表示背包重量为j,现有i个物品装入包中,物品编号依次是1,2,3,4,5,6...i...,从i个物品中选择,使得背包中物品的价值最大
* 当j==0时候,i个物品中一个都不能选择
* 当j==1时候,
* <b>难点在于如何用编码表示选择第i个物品放入背包,放入与不放入怎么用代码体现</b>
* 用totalSize表示物品个数
*/
/**
*
* knapsack类表示背包
*
*/
class Item{
private int weight;//wu
private int value;
public Item(int weight, int value){
this.weight = weight;
this.value = value;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString(){
return "Item[weight=" + weight + ", value=" + value + "]";
}
}
public class KnapsackDemo {
@Test
public void test(){
//int itemSize = 5;//有5个物品
int sackWeight = 17;//背包可以接受的总重量是16
List<Item> items = new ArrayList<Item>();
items.add(new Item(1, 1));
items.add(new Item(1, 2));
items.add(new Item(2, 2));
items.add(new Item(4, 10));
items.add(new Item(12, 4));
// items.add(new Item(3, 4));
// items.add(new Item(4, 5));
// items.add(new Item(7, 10));
// //items.add(new Item(4, 10));
// items.add(new Item(8, 11));
// items.add(new Item(9, 13));
//int[] w =
//Item[] item
//int values1 = solve( sackWeight, items);
int values2 = solve2( sackWeight, items);
//System.out.println("this is values1" + values1);
System.out.println("this is values2" + values2);
//
}
public int solve(int sackWeight, List<Item> items){
int itemSize = items.size();
//定义一个二维数组
int [][] c = new int[itemSize + 1][sackWeight + 1];
int totalValue = 0;
// while(true){
//
// }
// while(true){
//
// }
for(int i = 0; i <= items.size(); i++){
Item item = items.get(i);
int weight = item.getWeight();
int value = item.getValue();
for(int j = 0; j<= sackWeight ; j++){
if(i==0 || j==0){
//if(j==0){
c[i][j] = 0;
totalValue = c[i][j] = 0;
//return totalValue;
// System.out.println(0);
System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
}else{
//if(weight > j & i>= 1){
if(weight > j ){
//标号为i的物品不放人背包,且此时背包中的物品的价值总和达到最大
//还有一种情况是重量超了,放不下该物品
// c[i][j] = c[i-1][j]; //重量超了,放不下该物品
c[i][j] = c[i-1][j];
totalValue = c[i][j];
System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
// System.out.println(c[i][j]);
// return totalValue;
}else{
//标号为i的物品不放人背包,且此时背包中的物品的价值总和达到最大
// c[i][j] = c[i-1][j];
//标号为i的物品放入背包
// c[i][j] = c[i-1][(sackWeight - w[i])] + v[j];
c[i][j] = Math.max(c[i-1][(j - weight)] + value, c[i-1][j]);
//if()
if(c[i][j] > c[i-1][j]){
System.out.println("choose"+ i);
}
System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
}
totalValue = c[i][j];
}
}
//return totalValue;
}
return totalValue;
}
public int solve2(int sackWeight, List<Item> items) {
int itemSize = items.size();
int [][] bestValues = new int[itemSize + 1][sackWeight + 1];
int bestValue = 0;
// 遍历背包的承重
for (int j = 0; j <= sackWeight; j++) {
// 遍历指定物品
for (int i = 0; i <= itemSize; i++) {
// 当背包不放入物品或承重为0时,其最大价值均为0
if (i == 0 || j == 0) {
bestValues[i][j] = 0;
} else {
// 如果第 i个物品重量大于总承重,则最优解存在于前 i-1 个背包中
if (j < items.get(i-1).getWeight()) {
bestValues[i][j] = bestValues[i - 1][j];
} else {
// 如果第 i个物品不大于总承重,则最优解要么是包含第 i个背包的最优解,
// 要么是不包含第 i个背包的最优解, 取两者最大值
// int weight = bags[i - 1].getWeight();
int weight = items.get(i-1).getWeight();
int value = items.get(i-1).getValue();
bestValues[i][j] = Math.max(bestValues[i - 1][j], value
+ bestValues[i - 1][j - weight]);
}
}
}
}
return bestValue = bestValues[itemSize][sackWeight];
}
// public int getBestValue() {
// return bestValue;
// }
}
算法-01背包2
猜你喜欢
转载自blog.csdn.net/jjf09/article/details/77728400
今日推荐
周排行