KC的瓷器

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

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

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

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

接下来2到n+1行,第i行第一个数表示第i排柜子的商品数量Si,接下来Si个数表示从左到右每个商品的价值。
输出
输出文件只有一个正整数,即m个商品最大的总价值。
输入样例
输入1:
2 3
3 3 7 2
3 4 1 5

输入2:
1 3
4 4 3 1 2
输出样例
输出1:
15

样例解释1:
取第一排的最左边两个和第二排的最右边那个。总价直为3+7+5=15;

输出2:
9

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

.
.
.
.
.
.
分析
设s[i][j]表示第i行的前缀和

设a[i][j]表示第i行选j个数的最大值,num为第i行共有几个数
则a[i][j]=max(s[i][k]+(s[i][num]-s[i][num-j+k])) //前面选k个,后面选j-k个

设f[i][j]表示前i行选j个数的最大值
则f[i][j]=max(f[i-1][j-k]+a[i][k])

答案为f[n][m]

.
.
.
.
.
.
.
程序:

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

int n,m,num[200],s[200][200],a[200][200],f[200][10010];

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&num[i]);
		for (int j=1;j<=num[i];j++)
		{
			int x;
			scanf("%d",&x);
			s[i][j]=s[i][j-1]+x;
	    }
	}
	for (int i=1;i<=n;i++)
		for (int j=1;j<=num[i];j++)
			for (int k=0;k<=j;k++)
				a[i][j]=max(a[i][j],s[i][k]+(s[i][num[i]]-s[i][num[i]-j+k]));
    for (int i=1;i<=n;i++)
    	for (int j=1;j<=m;j++)
    		for (int k=0;k<=min(num[i],j);k++)
				f[i][j]=max(f[i][j],f[i-1][j-k]+a[i][k]);
    printf("%d",f[n][m]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值