背包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';
}

 

posted on 2019-06-29 15:44  zsben  阅读(266)  评论(0编辑  收藏  举报

导航