经典模型 动态规划(dp数组)

  1. 由经典的 01背包问题 入手
  • 已知:背包最大容积pack_max ,物品总数thing_max(每件物品的体积tiji ,价值val)
  • 求解:背包可装入物品的总的最大价值是多少

思路:
子问题:第j体积状态(小于或等于)下最大价值=第j -1体积状态下第i件物品的可装入或者不可装入两种情况中的最大值

public class 背包问题 {
	static Thing[] things ;
	static int[] dp ;
	public static void main(String[] args) {
		//记录输入
		Scanner sc = new Scanner(System.in);
		int pack_max =sc.nextInt(); 		//背包体积最大值
		int thing_max =sc.nextInt();		//物品总数
		things =new Thing[thing_max +1];
		dp =new int[pack_max +1]; //初始化每一种体积状态下的价值为‘0’
 		for(int i =1 ;i <=thing_max ;i ++) {things[i] =new Thing(sc.nextInt() ,sc.nextInt());}
		sc.close();
		//递推遍历所有物品
		for(int i =1 ;i <=thing_max ;i ++) {
			for(int j =pack_max ;j >=things[i].tiji ;j --)	//子问题分解,倒序遍历,保证dp[j]均只被修改一次
				//转移方程
				dp[j] =Math.max(dp[j], dp[j -things[i].tiji] +things[i].val);
		}
		//输出结果
		System.out.println(dp[pack_max]);
	}
}

class Thing{
	int tiji;	//体积
	int val;	//价值
	public Thing(int tiji, int val) {
		super();
		this.tiji = tiji;
		this.val = val;
	}
}
  1. 完全背包问题
  • 已知:普通背包问题条件下,每i件物品的数量都可以是多个的(可视为物品总数是无限多的)
  • 求解:背包最大的总的价值

思路:
重复遍历第i件物品->dp[j]应实时修改以取得最大值

public class 完全背包 {
	static Thing[] things ;
	static int[] dp ;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int pack_max =sc.nextInt(); 		
		int thing_max =sc.nextInt();		
		things =new Thing[thing_max +1];
		dp =new int[pack_max +1];
 		for(int i =1 ;i <=thing_max ;i ++) {things[i] =new Thing(sc.nextInt() ,sc.nextInt());}
		sc.close();
		for(int i =0 ;i <=thing_max ;i ++) dp[i] =0;	
		for(int i =1 ;i <=thing_max ;i ++) {
			for(int j =things[i].tiji ;j <=pack_max ;j ++)	//正序遍历物品,dp[j]将被实时修改为j体积状态下的最大值
				dp[j] =Math.max(dp[j], dp[j -things[i].tiji] +things[i].val);
		}
		System.out.println(dp[pack_max]);
	}
}

参考:
简单的动规实现案例-三角形
背包问题
王国的故事-动规的实现需要考虑的要素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肯尼思布赖恩埃德蒙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值