算法java实现--回溯法--0-1背包问题

0-1背包问题的java实现(回溯法)

具体问题描述以及C/C++实现参见网址

http://blog.csdn.net/liufeng_king/article/details/8764319

/**
 * 0-1背包问题--回溯法
 * @author Lican
 *
 */
public class Knapsack {
	public static class Element implements Comparable{
		int id;//物品编号
		double d;
		public Element(int id,double d){
			this.id=id;
			this.d=d;
		}
		@Override
		public int compareTo(Object x) {
			double xd=((Element)x).d;//递减顺序排列
			if(d<xd) return -1;
			if(d==xd) return 0;
			return 1;
		}
	}
	double c;//背包容量
	int n;//物品数
	double[] w;//物品重量数组
	double[] p;//物品价值数组
	double cw;//当前重量
	double cp;//当前价值
	double bestp;//最优价值
	int[] x;//当前装入背包顺序
	int[] bestx;//最优装入背包顺序
	Element[] q;//q为单位重量价值数组
	public double knapsack(double[] pp,double[] ww,double cc){
		//初始化
		c=cc;
		n=pp.length-1;
		cw=0;
		cp=0;
		bestp=0;
		x=new int[n+1];
		bestx=new int[n+1];
		//q为单位重量价值数组
		q=new Element[n+1];
		for(int i=0;i<=n;i++){
			q[i]=new Element(i,pp[i]/ww[i]);
		}
		//将个物品依单位重量价值从大到小排列
		java.util.Arrays.sort(q);
		p=new double[n+1];
		w=new double[n+1];
		for(int i=1;i<=n;i++){
			p[i]=pp[q[i].id];
			w[i]=ww[q[i].id];
		}
		backtrack(1);
		return bestp;
	}
	public void backtrack(int i){
		if(i>n){//到达叶子节点
			bestp=cp;
			for(int j=1;j<=n;j++){//保存最优值对应的包的编号
				bestx[j]=x[j];
			}
			return;
		}
		if(cw+w[i]<=c){//左子树
			x[i]=1;
			cw+=w[i];
			cp+=p[i];
			backtrack(i+1);
			cw-=w[i];//恢复现场
			cp-=p[i];
		}
		if(bound(i+1)>bestp){
			x[i]=0;
			backtrack(i+1);
		}
	}
	public double bound(int i){//上界函数
		double cleft=c-cw;
		double bound=cp;
		while(i<=n&&w[i]<=cleft){
			cleft-=w[i];
			bound+=p[i];
			i++;
		}
		if(i<=n){
			bound+=p[i]*cleft/w[i];
		}
		return bound;
	}
	public static void main(String[] args) {
		double[] weight={0,71,34,82,23,1,88,12,57,10,68,5,33,37,69,98,24,26,83,16,26,18,43,52,71,22,65,68,8,40,40,24,72,16,34,10,19,28,13,34,98,29,31,79,33,60,74,44,56,54,17};
		double[] price={0,26,59,30,19,66,85,94,8,3,44,5,1,41,82,76,1,12,81,73,32,74,54,62,41,19,10,65,53,56,53,70,66,58,22,72,33,96,88,68,45,44,61,78,78,6,66,11,59,83,48};
		double cc=300;
		//double[] weight={0,7,3,4,5};
		//double[] price={0,42,12,40,25};
		//double cc=10;
		Knapsack k=new Knapsack();
		double best=k.knapsack(price,weight,cc);
		System.out.println("最优值:"+best);
		System.out.println("选中的物品编号分别是:");
		for(int i=1;i<k.bestx.length;i++){
			if(k.bestx[i]==1){
				System.out.print(k.q[i].id+" ");
			}
		}
	}
}
/*
 输出结果:
 
最优值:1063.0
选中的物品编号分别是:
5 7 35 38 28 19 21 33 37 31 50 44 39 42 2 11 
*/

    原文作者:回溯法
    原文地址: https://blog.csdn.net/lican19911221/article/details/26160673
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞