回溯法01背包问题

问题描述:
给定n种物品和一背包。物品i的重量是wi>0,其价值为vi>0,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
源代码:

public class 回溯法01背包{

private static int[] p;//物品的价值数组
private static int[] w;//物品的重量数组
private static int c;//最大可以拿的重量
private static int count;//物品的个数
private static int cw;//当前的重量
private static int cp;//当前的价值
static int bestp;//目前最优装载的价值
private static int[] cx;//存放当前解
private static int[] bestx;//存放最终解
public static int Loading(int[] ww,int[] pp, int cc) {
//初始化数据成员,数组下标从1开始
count = ww.length - 1;
w = ww;
p = pp;
c = cc;
cw = 0;
bestp = 0;
cx = new int[count+1];
bestx = new int[count+1];
//调用回溯法计算
BackTrack(1);
return bestp;   
}

//BackTrack函数

public static void BackTrack(int t) {
if(t>count) {//到达叶结点
    if(cp>bestp) {//若当前解值>最优解值
    	//将当前解数组记录在最优解数组中
        for(int i = 1;i<=count;i++) 
            bestx[i] = cx[i];
        bestp = cp;//同时更新最优解值
    }
    return;
}
if(cw + w[t] <= c) {//搜索左子树,判断是否可放入
    cx[t] = 1;//放入
    cp += p[t];//同步更新当前背包的总价值     
    cw += w[t];//同步更新当前背包的重量
    BackTrack(t+1);//深度搜索进入下一层
    cp -= p[t];//回溯复原
    cw -= w[t];//回溯复原
    cx[t] = 0;//拿出
}
if(bound(t+1)>bestp)//如若符合条件则搜索右子树
     BackTrack(t+1);
}

//计算上界函数,功能为剪枝

static double bound(int i){   //判断当前背包的总价值cp+剩余容量可容纳的最大价值<=当前最优价值
double leftw= c-cw;//剩余背包容量
double b = cp;//记录当前背包的总价值cp,最后求上界
//以物品单位重量价值递减次序装入物品
while(i<=count && w[i]<=leftw)
{
    leftw-=w[i];
    b+=w[i];
    i++;
}
//装满背包
if(i<=count)
    b+=w[i]/w[i]*leftw;
return b;//返回计算出的上界
}

//将物品按单价升序的方法

public static void sort(int w1[],int p1[]) {
for(int i=1;i<w1.length;i++)
	  for(int j=i;j<w1.length;j++) {
		if(   (double)(p1[j])/w1[j]>(double)(p1[i])/w1[i]  ) {
			int tempw,tempp;
			tempw=w1[i];
			w1[i]=w1[j];
			w1[j]=tempw;
			tempp=p1[i];
			p1[i]=p1[j];
			p1[j]=tempp;
	   }
    }
}

//展示物品重量价值的方法

public static void show(int w[],int p[]) {
for(int i=1;i<w.length;i++)
System.out.println((i)+"号物件质量:"+w[i]+"   价值:"+p[i]);
}
//打印bestx(最优)方案
public static void showresult(int bestx[]) {
System.out.print("放入物品编号为:");
for(int i=1;i<bestx.length;i++)
	if(bestx[i]==1)
		System.out.print( i +"号  ");
}

//主函数用于测试

 public static void main(String[] args)  {
//物品重量数组
int[] w1 = {0,15,25,40,20,15,24,28};
//物品价值数组
int[] p1 = {0,10,5 ,20,2 ,14,23,10};
int c1 = 30;//最大容量
System.out.println("物品信息为:");
show(w1,p1);//展示物品信息
System.out.println("排序后物品信息为:");
sort(w1,p1); //将物品按单价排序
show(w1,p1);//展示排序后物品信息
//执行
Loading(w1,p1,c1);
//显示结果
showresult(bestx);
System.out.println("最优装载为:" + bestp);
}

}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值