思路:比较容易想到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 = + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +; LL dp[N][];
int n, k, a[N], f[N], h[N];
int cnt[M], num[M];
int main() { scanf("%d%d", &n, &k);
for(int i = ; i <= k * n; i++) {
scanf("%d", &a[i]);
cnt[a[i]]++;
} for(int i = ; i <= n; i++) {
scanf("%d", &f[i]);
num[f[i]]++;
} for(int i = ; i <= k; i++) {
scanf("%d", &h[i]);
} for(int i = ; i <= n * k; i++) {
dp[i][] = h[min(k, i)];
for(int j = ; j <= n; j++) {
for(int u = ; i - u >= && u <= k; u++) {
dp[i][j] = max(dp[i][j], dp[i - u][j - ] + h[u]);
}
}
} LL ans = ;
for(int i = ; i <= 1e5; i++) {
if(num[i]) {
ans += dp[cnt[i]][num[i]];
}
} printf("%lld\n", ans);
return ;
}
/*
*/