B. 小 A 的卡牌游戏 题解(贪心优化dp)

题目链接

有一个显然的 (O(n^3))dp,无法通过此题。

考虑如果只有两类卡组 a 和 b ,可以将每次 “3pick” 按 b − a 排序后贪心地先选择其中一类,再选另一类。
基于这个贪心,我们考虑对另一类卡组进行 dp。f(i, j) 表示前 i 次 “3pick” 中,有 j
次选择了第三类;没有选第三类的一定是根据前面的贪心选择优先选其中一类,而再选另一类。
复杂度:(O(n^2))

主要是要考虑到贪心的方面去写来优化dp

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=5e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int num[4];
int n;
ll ans=0;
ll dp[maxn][maxn];
struct node{
    int a,b,c;
}e[maxn];
bool cmp(node x,node y){
    return x.b-x.a>y.b-y.a;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>num[1]>>num[2]>>num[3];
    for(int i=1;i<=n;i++){
        cin>>e[i].a>>e[i].b>>e[i].c;
    }
    sort(e+1,e+1+n,cmp);
    for(int i=0;i<=n;i++){
        for(int j=0;j<=n;j++){
            dp[i][j]=-inf;
        }
    }
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=min(i,num[3]);j++){
            if(j!=0){// 选c
                dp[i][j]=max(dp[i][j],dp[i-1][j-1]+e[i].c);
            }
            if(i-j<=num[2]){ //选b
                dp[i][j]=max(dp[i][j],dp[i-1][j]+e[i].b);
            }else{
                dp[i][j]=max(dp[i][j],dp[i-1][j]+e[i].a);
            }
        }
    }
    cout<<dp[n][num[3]]<<'
';
    return 0;
}


不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15317040.html