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\n", ans);return 0; } /* */