题目本质:贪心+01背包(dp)
题目思路:dp[i][j] 表示考虑前 i 台计算机,能够获得 j 个核心时,所能获得的最大价值。将其可以优化为dp[i] 表示能够获得 i 个核心时,所能获得的最大价值。
状态转移方程:
对于原来n 台计算机,可得状态转移方程:
dp[j+p[i].c]=max(dp[j+p[i].c],dp[j]+p[i].v);
对于m台顾客需求的计算机,可得状态转移方程:
dp[j]=max(dp[j],dp[j+p[i].c]+p[i].v);
将数组初始化为无穷小,利用max找最大值,用cnt记录最大利润。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2*1e3+5;
const int MAXM=2*1e5+5;
ll n,m;
ll dp[MAXM];
ll cnt,ans;
struct node{
ll c,f,v;
}p[MAXN*2];
bool cmp(node x,node y){
if (x.f!=y.f){
return x.f>y.f;
}
return x.v<y.v;
}
int main(){
memset(dp,-0x3f,sizeof(dp));
scanf("%lld",&n);
for(int i=1;i<=n;++i){
scanf("%lld %lld %lld",&p[i].c,&p[i].f,&p[i].v);
p[i].v=-p[i].v;
}
scanf("%lld",&m);
for(int i=n+1;i<=n+m;++i){
scanf("%lld %lld %lld",&p[i].c,&p[i].f,&p[i].v);
}
sort(p+1,p+n+m+1,cmp);
dp[0]=0;
for(int i=1;i<=n+m;++i){
if (p[i].v>0){
for(int j=0;j<=cnt;++j){
dp[j]=max(dp[j],dp[j+p[i].c]+p[i].v);
}
}
else{
for(int j=cnt;j>=0;--j){
dp[j+p[i].c]=max(dp[j+p[i].c],dp[j]+p[i].v);
}
cnt=cnt+p[i].c;
}
}
for(int i=0;i<=cnt;++i){
ans=max(ans,dp[i]);
}
printf("%lld\n",ans);
return 0;
}