0-1背包问题——回溯法
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。
问应如何选择装入背包的物品,使得在总重量不超过背包的容量C的前提下装入背包中物品的总价值最大?
package com.lanxi.demo1; public class Package { static int n = 5;//给定物品数 int capacity = 15;//背包容量 int[] weight = {3,6,1,2,7};//物品重量 double[] value = {6,5,9,2,7};//物品价值 int maxValue = 0;//最大价值 int tempValue; int tempWeight; int[] way = new int[n];//存放方式 static int[] bestWay = new int[n];//价值最大存放方式 public void BackTrack(int t){ //已经搜索到根节点 if(t>n-1){ if(tempValue > maxValue){ maxValue = tempValue; for(int i=0;i<n;i++)//价值最大 bestWay[i] = way[i]; } return ; } //搜索左边节点 if(tempWeight + weight[t] <= capacity){ //总的放入的物品重量要小于背包 tempWeight += weight[t];//质量加 tempValue += value[t];//价值加 way[t] = 1;//放入后赋值为1 BackTrack(t+1); tempWeight -= weight[t]; tempValue -= value[t]; way[t] = 0; } //不装入这个物品,直接搜索右边的节点 if( Bound(t+1) >= maxValue){ BackTrack(t+1); } } //用于计算剩余物品的最高价值上界 public double Bound(int k){ double maxLeft = tempValue; int leftWeight = capacity - tempWeight;//剩余背包容量 //尽力依照单位重量价值次序装剩余的物品 while(k <= n-1 && leftWeight > weight[k] ){ leftWeight -= weight[k]; maxLeft += value[k]; k++; } //不能装时,用下一个物品的单位重量价值折算到剩余空间。 if( k <= n-1){ maxLeft += value[k]/weight[k]*leftWeight; } return maxLeft; } public static void main(String[] args){ Package b = new Package(); b.BackTrack(0);//设第1个商品序列号为0 System.out.println("该背包能够取到的最大价值为:"+b.maxValue); System.out.println("取出的方法为:"); for (int i = 0; i < n; i++) { System.out.print(bestWay[i]+" "); } } }
时间最会骗人,但也能让你明白,这个世界上没有什么是不能失去的,留下的尽力珍惜,得不到的都不重要