Codeforces 148E. Porcelain
問題
n個の棚がある。棚から合計m個の品を取りたい。
それぞれの棚は、先頭または末尾からしか品物を取り出すことは出来ない。
それぞれの棚の品物の価値が与えられたとき、
取り出せる価値の合計の最大値はいくつか、求めよ。
制約条件
n≦100, m≦10000
それぞれの棚の品物の数≦100
それぞれの品物の価値≦100
方針
棚ごとに、i個品物を取り出すときの価値の最大値を前計算により求める。
これは、i個のうちj個を先頭から取り出し、i-j個を末尾から取り出すとして、jを全通り試せばいい。
その後、以下のような動的計画法により答えを求める。
dp[i]をi個の品物で得られる価値の最大値とする。
これを、棚ごとに更新していく。
ソースコード
int dp[10001]; int num[100], mx[100][101]; void calc(int *a, int n, int *s){ int sum[101]={}; rep(i,n)sum[i+1]=sum[i]+s[i]; for(int i=1;i<=n;i++){ rep(l,i+1)a[i]=max(a[i], sum[l]+sum[n]-sum[n-i+l]); } } void run() { int n, m; cin>>n>>m; rep(i,n){ int s[100]; cin>>num[i]; rep(j,num[i])cin>>s[j]; calc(mx[i], num[i], s); } memset(dp,-1,sizeof(dp)); dp[0]=0; rep(i,n)for(int j=m;j>=0;j--)if(dp[j]>=0){ rep(k,num[i]+1)if(j+k<=m)dp[j+k]=max(dp[j+k], dp[j]+mx[i][k]); } cout<<dp[m]<<endl; }