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]);
}