洛谷 P1063 能量项链 & [NOIP2006提高组](区间dp,断环为链)
传送门
解题思路
个人感觉难度应该在蓝题左右
(可能是我太弱了趴)
首先我们知道,那个所谓的头标记和尾标记,在合并区间[l...r]时,n和m是确定了的(即l的头标记和r的尾标记),只差中间的r,所以我们可以枚举k(断点)。
然后我们又可以得出,对于合并区间[l...r],最终得分为(dp[i][k]+dp[k+1][j]+a[i][0]*a[k][1]*a[j][1]),就是左边区间的值加上右区间的值再加上合并的得分。
对于每一个k,a[k][1]是一个定值,所以很显然,dp[i][k]和dp[k+1][j]一定要保证最大值,这也就满足了最优子结构。
因为区间合并后,头标记和尾标记并没有任何改变,所以满足无后效性。
所以可以放心地使用区间dp了。
最后因为是环形,所以断环为链即可解决。
AC代码
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=205; 5 int n,a[maxn][2],dp[maxn][maxn],ans; 6 int main() 7 { 8 cin>>n; 9 for(int i=1;i<=n;i++){ 10 cin>>a[i][0]; 11 a[i+n][0]=a[i][0]; 12 a[i-1][1]=a[i][0]; 13 a[i+n-1][1]=a[i+n][0]; 14 } 15 for(int len=2;len<=n;len++){ 16 for(int i=1;i<=2*n-1;i++){ 17 int j=i+len-1; 18 if(j>2*n-1) break; 19 for(int k=i;k<j;k++){ 20 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+a[i][0]*a[k][1]*a[j][1]); 21 } 22 } 23 } 24 for(int i=1;i<=n;i++){ 25 ans=max(dp[i][i+n-1],ans); 26 } 27 cout<<ans; 28 return 0; 29 }
//NOIP2006提高组 t1