【DP】KC的瓷器(porcelain)

D e s c r i p t i o n Description Description

KC来到了一个盛产瓷器的国度。他来到了一位商人的店铺。在这个店铺中,KC看到了一个有n(1<=n<=100)排的柜子,每排都有一些瓷器,每排不超过100个。那些精美的艺术品使KC一下心动了,决定从N排的商品中买下m(1<=m<=10000)个瓷器。

这个商人看KC的脸上长满了痘子,就像苔藓一样,跟精美的瓷器相比相差太多,认为这么精致的艺术品被这样的人买走艺术价值会大打折扣。商人感到不爽,于是规定每次取商品只能取其中一排的最左边或者最右边那个,想为难KC。

现在KC又获知每个瓷器的价值(用一个不超过100的正整数表示),他希望取出的m个商品的总价值最大。

I n p u t Input Input

输入文件的第一行包括两个正整数n,m;

接下来2到n+1行,第i行第一个数表示第i排柜子的商品数量Si,接下来Si个数表示从左到右每个商品的价值。

O u t p u t Output Output

输出文件只有一个正整数,即m个商品最大的总价值。

S a m p l e Sample Sample I n p u t Input Input#1
2 3
3 3 7 2
3 4 1 5
S a m p l e Sample Sample I n p u t Input Input#2
1 3
4 4 3 1 2
S a m p l e Sample Sample O u t p u t Output Output#1
15
S a m p l e Sample Sample O u t p u t Output Output#2
9

H i n t Hint Hint

对于10%的数据,Si=1,1<=i<=n。
对于另外10%的数据,n=1.

T r a i n Train Train o f of of T h o u g h t Thought Thought

S u m [ i ] [ j ] Sum[i][j] Sum[i][j]代表第 i i i排的前 j j j个的和
再设 d i s [ i ] [ j ] dis[i][j] dis[i][j]代表第 i i i排选 j j j个的最大值
这个的动态转移方程就是 d i s [ i ] [ j ] = S u m [ i ] [ k ] + ( S u m [ i ] [ A [ i ] ] − S u m [ i ] [ A [ i ] − ( j − k ) ] ) dis[i][j] = Sum[i][k] + (Sum[i][A[i]] - Sum[i][A[i] - (j - k)]) dis[i][j]=Sum[i][k]+(Sum[i][A[i]]Sum[i][A[i](jk)])
再再设 F [ i ] [ j ] F[i][j] F[i][j]代表前 i i i排选了 j j j个的最大值
动态转移方程是 F [ i ] [ j ] = F [ i ] [ j − k ] + d i s [ i ] [ k ] F[i][j] = F[i][j - k] + dis[i][k] F[i][j]=F[i][jk]+dis[i][k]

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int A[505][10005], S[505][10005], dis[505][10005], F[505][10005];
int n, m;

int main()
{
    
    
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i)
	{
    
    
		scanf("%d", &A[i][0]);
		for(int j = 1; j <= A[i][0]; ++j)
		{
    
    
			scanf("%d", &A[i][j]);
			S[i][j] = S[i][j - 1] + A[i][j];//算前缀和
		}
			
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= A[i][0]; j++)
			for(int k = 0; k <= j; ++k)
				dis[i][j] = max(dis[i][j], S[i][k] + S[i][A[i][0]] - S[i][A[i][0] - j + k]);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			for(int k = 0; k <= min(j, A[i][0]); ++k)
			F[i][j] = max(F[i][j], F[i - 1][j - k] + dis[i][k]);
	printf("%d", F[n][m]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/108108053
DP
DP?
今日推荐