标签: 区间dp
hdu4570 http://acm.hdu.edu.cn/showproblem.php?pid=4570
题意:这题题意理解变态的。转自大神博客:
这题题意确实有点难懂,起码对于我这个英语渣渣来说是这样,于是去别人的博客看了下题目意思,归纳起来如下:
给出一个长度为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层,所以 当 j-i 小于20的时候,dp[i][j]初始化为 a[i]* 2&(j-i+1), 否则初始化为一个INF
方程 dp[i][j]= min(dp[i][j], dp[i][k]+dp[k+1][j] ) i<=k<j
自WA点: 构造解时候,i 和 j都该逆序遍历
1 #include <iostream> 2 #define N 65 3 using namespace std; 4 5 const long long INF = 1LL<<50; 6 long long dp[N][N],a[N]; 7 8 int main() 9 { 10 int _; 11 cin>>_; 12 while(_--) 13 { 14 int n,i,j,k; 15 cin>>n; 16 for(i=0;i<n;i++) cin>>a[i]; 17 for(i=0;i<n;i++) 18 for(j=i;j<n;j++) 19 if(j-i<20) dp[i][j]=a[i]*(1<<(j-i+1)); 20 else dp[i][j]=INF; 21 for(i=n-1;i>=0;i--) 22 for(j=n-1;j>=i;j--) 23 for(k=i;k<j;k++) 24 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); 25 cout<<dp[0][n-1]<<endl; 26 } 27 return 0; 28 }