kick start Round A 2020 Plates (DP)

Problem

Dr. Patel has N stacks of plates. Each stack contains K plates. Each plate has a positive beauty value, describing how beautiful it looks.

Dr. Patel would like to take exactly P plates to use for dinner tonight. If he would like to take a plate in a stack, he must also take all of the plates above it in that stack as well.

Help Dr. Patel pick the P plates that would maximize the total sum of beauty values.

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the three integers N, K and P. Then, N lines follow. The i-th line contains K integers, describing the beauty values of each stack of plates from top to bottom.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the maximum total sum of beauty values that Dr. Patel could pick.

Limits

Time limit: 20 seconds per test set.
Memory limit: 1GB.
1 ≤ T ≤ 100.
1 ≤ K ≤ 30.
1 ≤ P ≤ N * K.
The beauty values are between 1 and 100, inclusive.

sample Input

 2
2 4 5
10 10 100 30
80 50 10 50
3 2 3
80 80
15 50
20 10

Sample Output

  Case #1: 250
Case #2: 180

In Sample Case #1, Dr. Patel needs to pick P = 5 plates:
He can pick the top 3 plates from the first stack (10 + 10 + 100 = 120).
He can pick the top 2 plates from the second stack (80 + 50 = 130) .
In total, the sum of beauty values is 250.

In Sample Case #2, Dr. Patel needs to pick P = 3 plates:
He can pick the top 2 plates from the first stack (80 + 80 = 160).
He can pick no plates from the second stack.
He can pick the top plate from the third stack (20).
In total, the sum of beauty values is 180.

Note: Unlike previous editions, in Kick Start 2020, all test sets are visible verdict test sets, meaning you receive instant feedback upon submission.


题目理解起来没有问题,重点是DP怎么写
注意到,拿下面的盘子必须把上面的都拿走,先来个前缀和数组,然后用dp[i]表示拿i个盘子的最大美化度,

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int w[2005],v[2005],dp[2005];
int main()
{
    int t,n,k,p,times=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&k,&p);
        memset(dp,0,sizeof(dp));
        int len=0,tmp,sum;
        for(int i=0;i<n;i++)
        {
            sum=0;
            for(int j=1;j<=k;j++)
            {
                scanf("%d",&tmp);
                sum+=tmp;
                w[++len]=j;//每次拿的时候,不同摞的盘子是不用把其他摞的都拿走的,所以记录下在原始摞的顺序。
                v[len]=sum;//用一维数组表示二维数组,每一摞的前缀
            }
        }
        for(int i=1;i<=len;i+=k)//每次跳过一摞
        {
            for(int j=p;j>=0;j--)
            {
                for(int x=i;x<i+k;x++)
                {
                    if(j>=w[x])
                        dp[j]=max(dp[j],dp[j-w[x]]+v[x]);//在新的一摞拿第x个,那么之前只能拿j-x个,
                    else
                        break;
                }
            }
        }
        printf("Case #%d: %d\n",++times,dp[p]);
    }
    return 0;
}
发布了50 篇原创文章 · 获赞 50 · 访问量 2706

猜你喜欢

转载自blog.csdn.net/weixin_45691686/article/details/105084832