Java之回溯法实现01背包

package knapsack;

public class Knasack_Backtracking {

	/*
	 * 使用回溯法实现01背包问题
	 */
	/**有4件物品*/
	static final int n=4;
	/**背包最大承重为9*/
	static final int maxWeight=9;
	/**4件物品的重量*/
	static double weight[]={0,2,3,4,5};
	/**4件物品的价值*/
	static double value[]={0,3,4,5,7};
	/**背包中当前重量*/
	static int currentWeight=0;
	/**背包中当前价值*/
	static int currentValue=0;
	/**当前最优价值*/
	static int bestValue=0;
	/**物品*/
	static Item items[]=new Item[n+1];
	/**记录当前规则中物品放了与否*/
	static int x[]=new int[n+1];
	/**记录最优规则的物品放了与否*/
	static int bestX[]=new int[n+1];
	
	public static void main(String[] args) {
		
		items[0]=new Item(0,0);
		for(int i=1;i<=n;i++){
			items[i]=new Item(i,value[i]/weight[i]);
		}
		
		//使用冒泡排序,按照每个物品的单位质量的价格降序排列
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n-i;j++){
				if(items[j].averagePrice<items[j+1].averagePrice){
					items[0].id=items[j+1].id;
					items[0].averagePrice=items[j+1].averagePrice;
					items[j+1].id=items[j].id;
					items[j+1].averagePrice=items[j].averagePrice;
					items[j].id=items[0].id;
					items[j].averagePrice=items[0].averagePrice;
				}
			}
		}
		
		System.out.print("最优时选择");
		backtrack(1);
		for(int i=1;i<=n;i++){
			if(bestX[i]==1)
			System.out.print(" 第"+i+"件 ");
		}
		System.out.print("物品,最优值为"+bestValue);
	}
	
	/**回溯算法
	 * @param t 当前层数*/
	public static void backtrack(int t){
		if(t>n){//超出层数,当前背包中的价值就是最优值
			bestValue=currentValue;
			for(int j=0;j<=n;j++)
				bestX[j]=x[j];
			return;
		}
		
		//可以放入下一个物品
		if(currentWeight+weight[items[t].id]<=maxWeight){
			x[items[t].id]=1;
			currentWeight+=weight[items[t].id];
			currentValue+=value[items[t].id];
			backtrack(t+1);
			currentWeight-=weight[items[t].id];
			currentValue-=value[items[t].id];
		}
		
		if(bound(t+1)>bestValue){//进入右子树
			x[items[t].id]=0;
			backtrack(t+1);
		}
	}
	
	/**
	 * 进入右子树时计算上界
	 * @param t 层数*/
	public static double bound(int t){
		double topBound=currentValue;//上界
		double leftWeight=maxWeight-currentWeight;
		//将整件物品放入
		while(t<=n&&leftWeight>=weight[items[t].id]){
			leftWeight-=weight[items[t].id];
			topBound+=value[items[t].id];
			t++;
		}
		//不能整件放入的切开放
		if(t<=n)
			topBound+=leftWeight*items[t].averagePrice;
		
		return topBound;
	}
}

class Item{
	/**物品编号*/
	int id;
	/**该物品单位质量的价格*/
	double averagePrice;
	
	public Item(int id,double averagePrice){
		this.id=id;
		this.averagePrice=averagePrice;
	}
}

自己写的,直接可用。


猜你喜欢

转载自blog.csdn.net/BaiFeng303/article/details/41220021
今日推荐