题目链接:https://vjudge.net/problem/ZOJ-4019
题意
有个容量为c的背包,两类物品,其权值分别为k1、k2,第一种物品有n个,第二种有m个,每个物体都有自己的体积。当放进一个物体进入背包时,其获得的价值的对应的权值k乘上放入当前物体后剩余的容量。现在问,能够获得的最大价值是多少?
思路:
因为价值与物体放入后剩余的容量有关,所以,对于同一类物品,先放入体积较小的物品,所以对于同一类的物品,按照体积从小到大排一下序。接下来,重要的是找到正确的动态规划方程。
用dp[i][j]表示,将i个第一种物品,j个第二种物品,放入背包中,所能获得的最大价值。
动态规划方程:dp[i][j]=dp[i-1][j]+V余*k1 || dp[i][j]=dp[i][j-1]+V余*k2; (V余>=0)
注意体积,可以用V[i][j]表示i个第一种物品,j个第二种物品放入后所占用的体积。
附上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
ll t,c,n,m,k1,k2;
ll a[2005],b[2005];
ll dp[2005][2005],sum[2005][2005];
int main()
{
cin>>t;
while(t--)
{
scanf("%lld%lld%lld",&k1,&k2,&c);
scanf("%lld%lld",&n,&m);
ll i,j,k;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(i=1;i<=m;i++)
scanf("%lld",&b[i]);
sort(a+1,a+n+1);sort(b+1,b+m+1);
j=max(n,m);
for(i=0;i<=j;i++)
{
for(k=0;k<=j;k++)dp[i][k]=0,sum[i][k]=0;//初始化
}
ll ans=0;
for(i=0;i<=n;i++){
for(j=0;j<=m;j++)
{
if(i>0&&(c-a[i]-sum[i-1][j])>=0)//动态规划方程的条件
{
if((dp[i-1][j]+k1*(c-a[i]-sum[i-1][j]))>dp[i][j]){
dp[i][j]=dp[i-1][j]+k1*(c-a[i]-sum[i-1][j]);
sum[i][j]=sum[i-1][j]+a[i];
}
}
if(j>0&&(c-b[j]-sum[i][j-1])>=0)//动态规划方程的条件
{
if(dp[i][j]<(dp[i][j-1]+k2*(c-b[j]-sum[i][j-1]))){
dp[i][j]=dp[i][j-1]+k2*(c-b[j]-sum[i][j-1]);
sum[i][j]=sum[i][j-1]+b[j];
}
}
ans=max(ans,dp[i][j]);
}
}
printf("%lld\n",ans);
}
return 0;
}