【NOIP2013模拟】KC的陶器

【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个的最优值求出,再根据每行的求出前几行的。

  1. 首先令pref[i,j]表示第i行前j个瓷器价值和,suff[i,j]表示第i行后j个瓷器价值和。
  2. 令take[i,j]表示在第i行取出任意j个的最优值,很明显,任意j个可以是前k个的和加上后j-k个的和,即take[i,j]=max{prep[i,k]+suff[i,j-k]}。
  3. 令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.

你可能感兴趣的:(DP)