背包dp+打表处理——cf999F
考虑每种c都是可以独立进行计算的,所以这题的答案等价于每种c的最优解之和
计算每种c的最优解:把问题转化成求出每种c的最大值,再转化成i个人分j张卡片的最大收益
dp[i,j]表示i个人分j张卡片的最大收益,由于h对于每种状态都是确定的,所以我们只要进行一次打表O(n*k*n*k),这个dp打表类似于给定n*k容量的背包,然后每次取体积不超过k的物品,取n次的价值最大
#include<bits/stdc++.h> using namespace std; #define maxn 100005 int dp[505][5005],n,k,f[maxn],c[maxn],h[maxn]; void init(){//处理出i个人分j张卡的最大收益,类似背包 for(int i=1;i<=n;i++) for(int j=0;j<=n*k;j++) for(int l=0;l<=min(j,k);l++) dp[i][j]=max(dp[i][j],dp[i-1][j-l]+h[l]); } int main(){ cin>>n>>k; for(int i=1;i<=n*k;i++){ int x;cin>>x; c[x]++; } for(int i=1;i<=n;i++){ int x;cin>>x; f[x]++; } for(int i=1;i<=k;i++)cin>>h[i]; init(); int ans=0; for(int i=0;i<=100000;i++) if(f[i]!=0)ans+=dp[f[i]][c[i]]; cout<<ans<<'\n'; }