CodeForces 148E Porcelain : 书橱有n层书架,每层书架有一些书,每次取书只能取任意层最左和最右,问取m本书最大价值:dp
预处理dp[i][j]表示i层取j本书最大价值,利用前缀和来处理,枚举不拿的中间一段,这样预处理O(n^3)
随后进行dp,dp[i][j]表示前i层取j本书最大价值,再枚举i层拿k本书,这样也是O(n^3),甚至接近100*10000*100,不过codeforce的速度还是承受住了==
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 int dp[105][105],Dp[105][10005],sum[105],a[105]; 6 int main() 7 { 8 int n,m,i,j,k,maxx,tmp,x; 9 scanf("%d%d",&n,&m); 10 memset(sum,0,sizeof(sum)); 11 memset(dp,0,sizeof(dp)); 12 for (i=1;i<=n;i++) 13 { 14 scanf("%d",&a[i]); 15 for (j=1;j<=a[i];j++){ 16 scanf("%d",&x); 17 sum[j]=sum[j-1]+x; 18 } 19 for (j=1;j<=a[i];j++) 20 for (k=1;k+a[i]-j-1<=a[i];k++) 21 dp[i][j]=max(dp[i][j], 22 sum[a[i]]-(sum[k+a[i]-j-1]-sum[k-1])); 23 } 24 memset(Dp,0,sizeof(Dp)); tmp=0; 25 for (i=1;i<=n;i++) 26 { 27 tmp+=a[i]; 28 for (j=1;j<=tmp;j++) 29 { 30 maxx=0; 31 for (k=0;k<=a[i];k++) 32 { 33 if (j<k) continue; 34 if (tmp-a[i]<j-k) continue; 35 maxx=max(maxx,Dp[i-1][j-k]+dp[i][k]); 36 } 37 Dp[i][j]=maxx; 38 } 39 } 40 printf("%d\n",Dp[n][m]); 41 }