Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 460 Accepted Submission(s):
175
给出一个长度为n的数列,将其分成若干段,要求最小,其中ai是每一段数列的第一项,bi是每一段的长度,l为将数列分成l段。
比如样例:n=7,A={1 2 4 4 5 4 3},将其分成1 2 4| 4 5| 4| 3,则其所用空间为1*2^3+4*2^2+4*2^1+3*2^1=38,而如果分成1 2| 4 4 5| 4 3,则其所用空间为1*2^2+4*2^3+4*2^2=52,比38大。
思路:区间dp
dp[i][j]表示i--j层最小的内存;
初始条件:全压缩或全不压缩
因为压缩不能超过20层,所以在小于20层时初始条件:
dp[i][j]=min((sum[j]-sum[i-1])*2,num[i]*pow(j-i)*2);
大于20层是只能不压缩
dp[i][j]=(sum[j]-sum[i-1])*2;
然后循环
dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]);
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 __int64 dp[70][70],a[70],sum[70]; 6 __int64 pow(__int64 x) 7 { 8 int i; 9 __int64 ans=1; 10 for(i=0;i<x;i++) 11 ans=ans*2; 12 return ans; 13 } 14 int main() 15 { 16 int t,i,n,len,j,k; 17 scanf("%d",&t); 18 while(t--) 19 { 20 sum[0]=0; 21 scanf("%d",&n); 22 for(i=1;i<=n;i++) 23 { 24 scanf("%I64d",&a[i]); 25 sum[i]=sum[i-1]+a[i]; 26 } 27 memset(dp,0,sizeof(dp)); 28 for(len=0;len<n;len++) 29 { 30 for(i=1;i<=n&&len+i<=n;i++) 31 { 32 j=len+i; 33 if(len<19) 34 dp[i][j]=min((sum[j]-sum[i-1])*2,a[i]*pow(j-i+1)); 35 else 36 dp[i][j]=(sum[j]-sum[i-1])*2; 37 for(k=i;k<=j;k++) 38 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); 39 } 40 } 41 printf("%I64d\n",dp[1][n]); 42 } 43 return 0; 44 }
原文:http://www.cnblogs.com/lxm940130740/p/3891796.html