jzoj 3413.【NOIP2013模拟】KC的瓷器 (Standard IO)

Description
KC来到了一个盛产瓷器的国度。他来到了一位商人的店铺。在这个店铺中,KC看到了一个有n(1<=n<=100)排的柜子,每排都有一些瓷器,每排不超过100个。那些精美的艺术品使KC一下心动了,决定从N排的商品中买下m(1<=m<=10000)个瓷器。
这个商人看KC的脸上长满了痘子,就像苔藓一样,跟精美的瓷器相比相差太多,认为这么精致的艺术品被这样的人买走艺术价值会大打折扣。商人感到不爽,于是规定每次取商品只能取其中一排的最左边或者最右边那个,想为难KC。
现在KC又获知每个瓷器的价值(用一个不超过100的正整数表示),他希望取出的m个商品的总价值最大。
Input
输入文件的第一行包括两个正整数n,m;
接下来2到n+1行,第i行第一个数表示第i排柜子的商品数量Si,接下来Si个数表示从左到右每个商品的价值。

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

Sample Input
输入1:

2 3
3 3 7 2
3 4 1 5

输入2:

1 3
4 4 3 1 2

Sample Output
输出1:

15

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

输出2:

9

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

//written by zzy

题目大意:

再n个数列中选m个数,只能从头或尾取,求最大价值

题解:

不难想到dp
si,j表第i行的前缀和
先设takei,j表从在第i行选j个物品的最大值
易推takei,j=max{si,k+(si,num-si,num-(j-k))}//从头选k个,尾选j-k个
再考虑从i行中选
有点类似于揹包
设f`i,j表在前i行中选j个物品的最大值
fi,j=max{fi-1,j-k+takei,k}//在第i行选k个物品
答案为fn,m

#include<iostream>
#include<algorithm>
#include<cstdio>
#define N 105
#define M 10005
using namespace std;

int i,j,k,n,m,x;
int num[N],s[N][N],take[N][N],f[N][M];

int main()
{
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++)
	{
		scanf("%d",&num[i]);
		for (j=1;j<=num[i];j++) {
		  scanf("%d",&x);
		  s[i][j]=s[i][j-1]+x;
	    }
	}
	for (i=1;i<=n;i++) {
	    for (j=1;j<=num[i];j++)
	     for (k=0;k<=j;k++)
	      take[i][j]=max(take[i][j],s[i][k]+(s[i][num[i]]-s[i][num[i]-j+k]));
    }
    for (i=1;i<=n;i++) {
    	for (j=1;j<=m;j++)
    	 for (k=0;k<=min(num[i],j);k++)
    	f[i][j]=max(f[i][j],f[i-1][j-k]+take[i][k]);
    }
    printf("%d",f[n][m]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章