回溯法 0 1背包 java,01背包問題(回溯法實現,java)

上兩天學習的回溯算法,老師讓我們回溯法來解決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);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值