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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.