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;
}