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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章