/**
* 有一个背包,背包总的承载重量是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<n;++i) {//动态规划状态转移
for(int j=0;j<=w;++j) {//不把第i个物品放入背包
if(states[i-1][j]==true) {
states[i][j] = states[i-1][j];
}
}
for(int j=0;j<=w-weight[i];++j) {//把第i个物品放入背包
if(states[i-1][j]==true) {
states[i][j+weight[i]]=true;
}
}
}
for(int i=w;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<n;i++) {
for(int j=w-items[i];j>=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<n;i++) {//初始化states
for(int j=0;j<w+1;++j) {
states[i][j] = -1;
}
}
states[0][0] = 0;
states[0][weight[0]] = value[0];
for(int i=1;i<n;i++) {//动态规划,状态转移
for(int j=0;j<=w;j++) {//不选择第i个物品
if(states[i-1][j]>=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<n;i++) {//动态规划
for(int j=0;j<=3*w;j++) {//不购买第i个商品
if(states[i-1][j]==true) states[i][j] = states[i-1][j];
}
for(int j=0;j<=(3*w-items[i]);j++) {
if(states[i-1][j]==true) states[i][j+items[i]]=true;
}
}
int j;
for(j=w;j<3*w+1;j++) {
if(states[n-1][j]==true) break;//输出结果大于等于w的最小值
}
if(j==-1) return;//没有可行解
for(int i=n-1;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]);
}
}
01-05
3882
04-23
4万+