Codeforces Round #490 (Div. 3) F

F - Cards and Joy

思路:比较容易想到dp,直接dp感觉有点难,我们发现对于每一种数字要处理的情况都相同就是有 i 张牌 要给 j 个人分,

那么我们定义dp[ i ][ j ]表示 i 张牌给 j 个人分最大的价值可以得到dp方程如下:

dp[ i ][ j ] = max(dp[ i - u ][ j - 1 ] + f[ u ] )   u <= k 

暴力转移就好了。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 5000 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

LL dp[N][501];
int n, k, a[N], f[N], h[N];
int cnt[M], num[M];
int main() {

    scanf("%d%d", &n, &k);
    for(int i = 1; i <= k * n; i++) {
        scanf("%d", &a[i]);
        cnt[a[i]]++;
    }

    for(int i = 1; i <= n; i++) {
        scanf("%d", &f[i]);
        num[f[i]]++;
    }

    for(int i = 1; i <= k; i++) {
        scanf("%d", &h[i]);
    }

    for(int i = 1; i <= n * k; i++) {
        dp[i][1] = h[min(k, i)];
        for(int j = 2; j <= n; j++) {
            for(int u = 1; i - u >= 0 && u <= k; u++) {
                dp[i][j] = max(dp[i][j], dp[i - u][j - 1] + h[u]);
            }
        }
    }
    
    LL ans = 0;
    for(int i = 1; i <= 1e5; i++) {
        if(num[i]) {
            ans += dp[cnt[i]][num[i]];
        }
    }

    printf("%lld
", ans);
    return 0;
}
/*
*/
原文地址:https://www.cnblogs.com/CJLHY/p/9213154.html