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

CodeForces 999F Cards ans Joy

题目

◇题目传送门◆

题目大意

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

思路

非常裸的一道DP题。

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

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

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 ] 为数值为 i 的牌的数量, P [ i ] 为喜欢数值为 i 的人数,答案即为:

i = 0 M a x n u m f [ 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!

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

猜你喜欢

转载自blog.csdn.net/qq_37656398/article/details/81191529
今日推荐