回溯算法——背包问题

/**
 * 有一个背包,背包总的承载重量是Wkg。现在我们有n个物品,每个物品的重量不等,并且不可分割。
 * 我们现在期望选择几件物品,装载到背包中。在不超过背包所能装载重量的前提下,如何让背包中物品的总重量最大。
 * @author Administrator
 *
 */
public class HuiSuSuanFa {
	public static void main(String[] args) {
		int[] items = new int[]{11,9,7,6,5,};
		f(0,0,items,5,20);
		System.out.println("maxW="+maxW);
		
		System.out.println(Knapsack(new int[]{2,2,4,6,3},5,9));
	}
	
	/**
	 * 背包总的承载重量是Wkg。有n个物品,每个物品的重量不等,并且不可分割。我们现在期望选择几件物品,
	 * 装载到背包中。在不超过背包所能装载重量的前提下,如何让背包中物品的总重量最大。
	 * 
	 * 假设背包可承受重量20,物品个数5,物品重量存储在数组a中,那可以这样调用函数:
	 * f(0, 0, a, 5, 20)
	 * 
	 * @param i 表示考察到哪个物品了
	 * @param cw 表示当前已经装进去的物品的重量和
	 * @param items 表示每个物品的重量
	 * @param n 表示物品个数
	 * @param w 背包重量
	 */
	public static int maxW = Integer.MIN_VALUE;
	public static void f(int i,int cw,int[] items,int n,int w) {
		if(cw==w||i==n) {//cw==w表示装满了;i==n表示已经考察完所有的物品
			System.out.println("cw==w||i==n cw="+cw);
			if(cw>maxW) maxW = cw;
			return;
		}	
		System.out.println("不放入"+(i+1)+",cw="+cw);
		f(i+1,cw,items,n,w);//选择不装第i个数
		if(cw+items[i]<=w) {//已经超过可以背包承受的重量的时候,就不要再装了
			System.out.println("放入"+(i+1)+",cw="+(cw+items[i]));
			f(i+1,cw+items[i],items,n,w);//选择装第i个数
		}
	}
	
	/**
	 * 动态规划:背包总的承载重量是Wkg。有n个物品,每个物品的重量不等,并且不可分割。我们现在期望选择几件物品,
	 * 装载到背包中。在不超过背包所能装载重量的前提下,如何让背包中物品的总重量最大。
	 * @param weight 物品重量 {2,2,4,6,3}
	 * @param n 物品个数
	 * @param w 背包可承载重量
	 * @return
	 */
	public static int Knapsack(int[] weight,int n,int w) {
		boolean [][] states = new boolean[n][w+1];//默认值false
		states[0][0] = true;//第一行的数据要特殊处理,可以利用哨兵优化
		states[0][weight[0]] = true;
		
		for(int i=1;i=0;--i) {//输出结果
			if(states[n-1][i]==true) return i;
		}
		
		return 0;
	}
	
	/**
	 * 优化Knapsack:背包总的承载重量是Wkg。有n个物品,每个物品的重量不等,并且不可分割。我们现在期望选择几件物品,
	 * 装载到背包中。在不超过背包所能装载重量的前提下,如何让背包中物品的总重量最大。
	 * 
	 * @param items 物品重量 {2,2,4,6,3}
	 * @param n 物品个数
	 * @param w 背包可承载重量
	 * @return
	 */
	public static int Knapssack2(int[] items,int n,int w) {
		boolean[] states = new boolean[w+1];//默认值false
		states[0] = true;//第一行的数据要特殊处理,可以利用哨兵优化
		states[items[0]]=true;
		for(int i=1;i=0;--j) {
				if(states[j]==true) states[j+items[i]] = true;
			}
		}
		
		for(int i=w;i>=0;--i) {//输出结果
			if(states[i]==true) return i;
		}
		
		return 0;
	}
	
	/**
	 * 动态规划:重量一定,放入价值最大
	 * 对于一组不同重量、不同价值、不可分割的物品,我们选择将某些物品装入背包,在满足背包最大重量限制的前提下,
	 * 背包中可装入物品的总价值最大是多少呢?
	 * @param weight 物品重量 {2,2,4,6,3}
	 * @param value 物品价值
	 * @param n 物品个数
	 * @param w 背包可承载重量 
	 * @return
	 */
	public static int knapsack3(int[] weight,int[] value,int n,int w) {
		int[][] states = new int[n][w+1];
		for(int i=0;i=0) {
					states[i][j]=states[i-1][j];
				}
			}
			for(int j=0;j<=w-weight[i];j++) {
				int v = states[i-1][j]+value[j];
				if(v>states[i][j+weight[i]]) {
					states[i][j+weight[i]] = v;
				}
			}
		}
		
		//找出最大值
		int maxvalue = -1;
		for(int j=0;j<=w;j++) {
			if(states[n-1][j]>maxvalue) maxvalue = states[n-1][j];
		}
		
		return maxvalue;
	}
	
	/**
	 * 动态规划:找出最合适的满减
	 * 
	 * @param items 商品价格
	 * @param n 商品个数
	 * @param w 表示满减条件,比如200
	 */
	public static void doublelladvance(int[] items,int n,int w) {
		boolean[][] states = new boolean[n][3*w+1];//超过三倍就没有薅羊毛的价值了
		states[0][0] = true;//第一行的数据要特殊处理
		states[0][items[0]] = true;
		for(int i=0;i=1;--i) {//i表示二维数组中的行,j表示列
			if(j-items[i]>=0 && states[i-1][j-items[i]]==true) {
				System.out.println(items[i]+" ");//购买这个商品
				j = j -items[i];
			}//else 没有购买这个商品,j不变
		}
		if(j != 0) System.out.println(items[0]);
	}
}

你可能感兴趣的:(数据结构与算法,算法,java,开发语言)