【NOIP2013模拟】KC的瓷器 题解

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.

这是一道基础的DP题。

先预处理take[i][j],表示从第i排中取出j个瓷器的最大价值,以及a[i][j]表示第i排前j个瓷器的总价值。

考虑对于每一排取出最左边的k个,那么剩下的j-k个就是最右边的,1<=k<=c。易得:Take[i][j]=max(a[i][k]+a[i][c]-a[i][c-j+k]),c表示第i排的瓷器数目。

接下来进行动态规划,F[i][j]表示从前i排取出j个的最大价值。

那么F[i][j]=max(F[i-1][j-k]+take[i][k])

时间复杂度O(nmc)。大约是10^8,加上常数优化后在我的机器上可以在0.3s内出解


标准程序:


var g,a:array[0..100,0..10000] of longint;
ans:array[0..100,0..10000] of longint;
c:array[1..100] of longint;
n,m,i,j,k,m1:longint;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
begin
   


readln(n,m);
for i:=1 to n do
begin
read(c[i]);
for j:=1 to c[i] do
begin
read(a[i,j]);
//if j<>1 then
                        a[i,j]:=a[i,j]+a[i,j-1];
end;
end;
for i:=1 to n do
begin
for j:=1 to c[i] do
begin
for k:=0 to j do
begin
g[i,j]:=max(g[i,j],a[i,k]+a[i,c[i]]-a[i,c[i]-j+k]);
end;
end;
end;
for i:=1 to n do
begin
for j:=1 to m do
begin
for k:=0 to min(j,c[i]) do
begin
ans[i,j]:=max(ans[i,j],ans[i-1,j-k]+g[i,k]);
end;
end;
end;
writeln(ans[n,m]);
end.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值