上兩天學習的回溯算法,老師讓我們回溯法來解決01背包問題,
經過了幾天的改改增增,終於實現成功了。
自我感覺回溯算法思想,從左到右,一步一步,能走則走,不能則過!
下面直接貼代碼,代碼上詳細注釋!
import java.util.Arrays;
/**
* 回溯法的01背包
*
* @author anLA
*
*/
public class BagFBack {
private MyElement[] myelements; // 封裝的物品
private float s; // 背包容量
private float nowWeight = 0; // 記錄當前以拿重量
private float nowPrice = 0; // 記錄當前以拿價格
private float betterValue; // 記錄最多的價格
/*
* 構造方法,用於初始化各個變量
*/
public BagFBack(float[] w, float[] v, float s) {
myelements = new MyElement[w.length];
for (int i = 0; i < w.length; i++) {
myelements[i] = new MyElement();
myelements[i].v = v[i];
myelements[i].w = w[i];
}
this.s = s;
// 對數組進行價值排序,系統的是從小到大的,但我講MyElement改了,使得是從大到小
Arrays.sort(myelements);
System.out.println("物品價值" + "" + "物品重量");
for (int i = 0; i < myelements.length; i++) {
System.out.print(myelements[i].v + "" + myelements[i].w);
System.out.println();
}
}
public void traceBack(int t) {
if (t >= myelements.length) {
// 已經遍歷到最下一層,也就是最后一個
System.out.println("找到方法");
betterValue = nowPrice;
System.out.println("最終拿到: " + betterValue);
output(myelements);
return;
}
// 首先進入走左子樹
if (nowWeight + myelements[t].w < s) {
// 進入左子樹
nowWeight += myelements[t].w;
nowPrice += myelements[t].v;
myelements[t].take = true;
traceBack(t + 1);
// 還原現場
nowWeight -= myelements[t].w;
nowPrice -= myelements[t].v;
myelements[t].take = false;
}
// 進入右子樹,以及要進入的條件
if (bound(t + 1) > betterValue) {
traceBack(t + 1);
}
}
// 輸出方法,用於輸出
public void output(MyElement[] myelements2) {
System.out.print("拿重量為這些的物品:");
for (int i = 0; i < myelements2.length; i++) {
if (myelements2[i].take) {
System.out.print(myelements2[i].w + "");
}
}
}
/**
* 用於計算右邊的,如果右邊大些,就直接進入
*
* @param i
* @return
*/
public float bound(int i) {
// 計算上界
float cleft = s - nowWeight;
float bound = nowPrice;
// 以物品單位價值遞減順序裝入物品
while (i < myelements.length && cleft > myelements[i].v) {
cleft -= myelements[i].w;
bound += myelements[i].v;
i++;
myelements[i].take = true;
}
// // 如果最后一個不能整個放下去,那就裝滿背包,此問題討論01背包,要么裝,要么不裝,所以不用加這一句
// if (i < myelements.length) {
// bound += (myelements[i].v / myelements[i].w) * cleft;
// }
return bound;
}
/**
* 封裝為物品的類
*
* @author anLA
*
*/
class MyElement implements Comparable {
float w;
float v;
boolean take = false;
// 更改實現的方法,方便調用系統函數
@Override
public int compareTo(Object o) {
if (v / w < ((MyElement) o).v / ((MyElement) o).w) {
return 1; // 注意,此處主要用於排序,從大到小排序,所以故意反
} else {
return -1;
}
}
}
public static void main(String[] args) {
float[] w = { 3.4f, 2.5f, 6f, 4f, 9.0f };
float[] v = { 3f, 2.5f, 5f, 9f, 6.2f };
float s = 10;
BagFBack bagFBack = new BagFBack(w, v, s);
// 從第0層開始回溯
bagFBack.traceBack(0);
}
}