(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];
}
}
}
}