思路:比较容易想到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; } /* */
原文地址:https://www.cnblogs.com/CJLHY/p/9213154.html
时间: 2024-10-10 04:17:11