codeforce 999f dp

原题链接

emmmmmm就是利用无论怎样取几个人拿都是一样的   所以先把n张卡m个人拿的情况写出来最后求和

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<cstdlib>
#include<cmath>
#include<string>
#include<deque>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
LL n,k,q,m[505],z[15],ll,l,j,max1,ans,i,v[100005],w[100005],dp[5005][505];
int main()
{
    memset(w,0,sizeof(w));
    memset(v,0,sizeof(v));
    scanf("%lld%lld",&n,&k);
    for(i=0;i<n*k;i++)
    {
        scanf("%lld",&q);
        w[q]++;
    }
    max1=0;
    for(i=0;i<n;i++)
    {
        scanf("%lld",&m[i]);
        v[m[i]]++;
        max1=max(max1,m[i]);
    }
    for(i=1;i<=k;i++)
    {
        scanf("%lld",&z[i]);
    }
    ans=0;
    for (i = 1; i <= n*k; i++)//一直加到所有的牌  是有可能一个人拿所有的牌的
    {
        dp[i][1] = z[min(i, k)];//把全部的i张牌给1个人
        for (j = 2; j <= n; j++)
        {
            for (ll = 1; ll<= min(i, k); ll++)
            {
                dp[i][j] = max(dp[i][j], dp[i-ll][j-1]+z[ll]);//i张牌给j个人最多的分等于它本身和i-ll张牌分给j-1个人的最大值加ll张牌的分取大
            }
        }
    }
    for ( i = 0; i <= max1; i++)
        if (v[i])
            ans += dp[w[i]][v[i]];//把结果加上就行
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41886199/article/details/81274660