【NOIP2013模拟】KC的陶器
Time Limits: 1000 ms Memory Limits: 262144 KB
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
Input1:
2 3
3 3 7 2
3 4 1 5
Input2:
1 3
4 4 3 1 2
Sample Output
Output1:
15
样例解释1:
取第一排的最左边两个和第二排的最右边那个。总价直为3+7+5=15;
Output2:
9
Data Constraint
对于10%的数据,Si=1,1<=i<=n。
对于另外10%的数据,n=1
对于100%的数据,1<=n,Si<=100,1<=m<=10000
题目大意
有n行陶器,第i行有Si个陶器,每一个淘气有一个价值,现在要从任意一行的任意一端取一个陶器,共取m个陶器,求所有取出的陶器价值之和。
解题思路
我们可以将每一行取i个的最优值求出,再根据每行的求出前几行的。
- 首先令pref[i,j]表示第i行前j个瓷器价值和,suff[i,j]表示第i行后j个瓷器价值和。
- 令take[i,j]表示在第i行取出任意j个的最优值,很明显,任意j个可以是前k个的和加上后j-k个的和,即take[i,j]=max{prep[i,k]+suff[i,j-k]}。
- 令f[i,j]表示前i行拿了j个瓷器的最优值,显然背包即可。
Codes
var pref,suff,take:array[0..101]of longint;
f:array[0..100,0..10000] of longint;
n,w,i,j,k,c:longint;
function max(p,q:longint):longint;
begin
if p>q then exit(p) else exit(q);
end;
begin
read(n,w);
for i:=1 to n do
begin
read(c);
for j:=1 to c do
begin
read(pref[j]);
inc(pref[j],pref[j-1]);
end;
for j:=c downto 1 do suff[c-j+1]:=suff[c-j]+pref[j]-pref[j-1];
fillchar(take,sizeof(take),0);
f[i]:=f[i-1];
for j:=1 to c do
begin
for k:=0 to j do take[j]:=max(take[j],pref[k]+suff[j-k]);
for k:=0 to w-j do f[i,j+k]:=max(f[i,j+k],f[i-1,k]+take[j]);
end;
end;
writeln(f[n,w]);
end.