二维费用背包

               (1)问题描述

                         每一件物品都有两个费用,选择这个物品需要付出两种代价,对于每种代价都有一个最大值,问怎么选择物品可以获得最大的价值

               (2)分析

                         费用增加了一维,只要状态也增加一维即可。设dp[i][j]表示付出两种代价分别为i和j时可以获得的最大价值,那么状态转移方程就是:

                         dp[i][j] = max{dp[i][j],dp[i-a[k]][j-b[k]+value[k]}

                         这个状态转移方程同其他几种背包一样,都是省略了第一维第i个物品的状态。在二维费用背包问题下,如果每种物品只有一件,那么两个费用都按逆序循环;如果是完全背包,那么两个费用都按顺序循环。

                (3)例子

                         将数组中的2n个数分为2组,每组n个,使得两组的所有数字之和最接近。

                         因为要求必须为n个,那么当第一维为0,即表示必须有0个时,dp[0][j]=0,因为一个都不选肯定为0;其余均设为-INF,表示是非法解。

		int[] a = {1,9,3,7,5,6,4,6,8,2};
		int n = a.length;
		
		int sum = 0;
		for(int x:a)
			sum += x;
		
		int[][] dp = new int[n/2+1][sum/2+1];
		
		for(int i=0; i<=n/2; i++)
		{
			for(int j=0; j<=sum/2; j++)
			{
				dp[i][j] = -9999;
				dp[0][j] = 0;
			}
		}
		
		for(int i=1; i<=n; i++)
		{
			for(int j=n/2; j>=1; j--)
			{
				for(int k=sum/2; k>=0; k--)
				{
					if(k>=a[i-1])
					{
						if(dp[j][k] < dp[j-1][k-a[i-1]]+a[i-1])
							dp[j][k] = dp[j-1][k-a[i-1]]+a[i-1];
					}
				}
			}
		}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值