01背包问题

1 篇文章 0 订阅

动态规划:http://zh.wikipedia.org/zh-cn/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92#.E8.83.8C.E5.8C.85.E9.97.AE.E9.A2.98

直接看解法吧,貌似还是有问题。

 

 

package package01;

public class TestPackage01 {
	static OBJ[] objs={new OBJ(3,4),new OBJ(8,17),new OBJ(5,9),new OBJ(6,8),new OBJ(10,16)};//物品
	
	static int II=20;static int VV=20;static int[][] IVmap=new int[II][VV];//第I个物品放入体积为V的背包时的最大价值
	static int num=0;//计算的次数
	public static void main(String[] args) {
		for(int i=0;i<II;i++){//初始化为-1
			for(int j=0;j<VV;j++){
				IVmap[i][j]=-1;
			}
		}
		System.out.println(maxValue(4,11));//对objs中的这些背包来说,第五次放入物品的最大价值,就是最优解
		System.out.println(num);
		for(int i=0;i<II;i++){
			for(int j=0;j<VV;j++){
				System.out.print(" "+IVmap[i][j]);
			}
			System.out.println();
		}
	}
	/**
	 * 放第i件物品到体积为v的包里的最大价值
	 * @param i 从物品里取出一个物品放入包中,这个是第i次取出的物品。大于等于0
	 * 如果i是0,也就是第一次取物品时,取一个物品,放到体积为v的包里,最大价值是多少。
	 * @param v 一个体积为v的包,大于等于0
	 * @return 最大价值,应该是个大于等于0的数
	 */
	public static int maxValue(int i,int v){
		if (IVmap[i][v]>-1) {//看是否已经计算过//初始化为-1
			return IVmap[i][v];
		}
		num++;
		int val=0;
		if (i<1) {//第一次取物品时
			for (int j = 0; j < objs.length; j++) {
				if (objs[j].v<v) {
					val=max(val,objs[j].p);
				}
			}
		}else {
			for(int j=0;j < objs.length; j++) {//遍历所有的物品,找到i
				int VI=objs[j].v;//VI为第i个物品的体积
				int PI=objs[j].p;//PI为第i个物品的价值
				if (v<VI) {//当前物品无法放入背包
					val=maxValue(i-1,v);
				}else if(v>=VI){
					val= max(maxValue(i-1,v),maxValue(i-1,v-VI)+PI);//当前物品可以放入背包,也可以不放入
				}
				if(i==-1||v==0)val=0;//这是什么情况下会出现?
			}
		}
		IVmap[i][v]=val;//记录计算的结果
		return val;
	}
	private static int max(int val, int p) {
		return p>val?p:val;
	}
}
class OBJ{
	public int v;
	public int p;
	public OBJ(int v,int p){
		this.v=v;
		this.p=p;
	}
}

 运行结果:

 

17
31
 0 0 0 0 -1 4 9 -1 9 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1
 0 0 0 0 -1 4 9 -1 9 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1
 0 0 0 0 -1 4 9 -1 9 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1
 -1 0 -1 0 -1 4 9 -1 9 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1
 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值