【CodeForces】【DP】999F-Cards and Joy

CodeForces 999F Cards ans Joy

题目

◇题目传送门◆

题目大意

N N 个人,每人要得到K张牌,牌上有不同的数字,记第 i i 张牌上的数字为ci。第 i i 个人有自己喜欢的数字,记为fi。若每个人能够得到 i i 张自己所喜欢的牌,则能够获得hi的快乐值。将每个人所获得的快乐值的总和称为总快乐值,求能获得的最大总快乐值。

思路

非常裸的一道DP题。

我们记 f[i][j] f [ i ] [ j ] 为将 i i 张相同的牌分给j个所获得的最大快乐值。

很容易得出状态转移方程:

f[i][j]={h[min(i,K)](1iN×K)max{f[ik][j1]+h[k]}(1iN×T,2jN,1kmin(i,K)) f [ i ] [ j ] = { m a x { f [ i − k ] [ j − 1 ] + h [ k ] } ( 1 ≤ i ≤ N × T , 2 ≤ j ≤ N , 1 ≤ k ≤ m i n ( i , K ) ) h [ m i n ( i , K ) ] ( 1 ≤ i ≤ N × K )

我们同时记 C[i] C [ i ] 为数值为 i i 的牌的数量,P[i]为喜欢数值为 i i 的人数,答案即为:

i=0Maxnumf[C[i]][P[i]](P[i]0)

实现细节

注意:可能会炸int,请使用long long

正解代码

#include<cstdio>
#include<algorithm>
using namespace std;
const int Maxn=500,Maxk=10,Maxnum=1e5;
int N,K;
int cad[Maxn*Maxk+5],peo[Maxn+5],H[Maxk+5];
int C[Maxnum+5],P[Maxnum+5];
int dp[Maxn*Maxk+5][Maxn+5];

void ReadIn() {
    scanf("%d %d",&N,&K);
    for(int i=1;i<=N*K;i++) {
        scanf("%d",&cad[i]);
        C[cad[i]]++;
    }
    for(int i=1;i<=N;i++) {
        scanf("%d",&peo[i]);
        P[peo[i]]++;
    }
    for(int i=1;i<=K;i++)
        scanf("%d",&H[i]);
}

long long GetAns() {
    long long ret=0;
    for(int i=0;i<=Maxnum;i++)
        if(P[i])ret+=dp[C[i]][P[i]];
    return ret;
}

int main() {
    #ifdef LOACL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    ReadIn();

    for(int i=1;i<=N*K;i++) {
        dp[i][1]=H[min(i,K)];
        for(int j=2;j<=N;j++)
            for(int k=1;k<=min(i,K);k++)
                dp[i][j]=max(dp[i][j],dp[i-k][j-1]+H[k]);
    }

    printf("%d\n",GetAns());
    return 0;
}

Thanks For Reading!

如有不妥之处请在评论中指出,我会尽快回复!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值