洛谷 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
 2 #include
 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){
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

你可能感兴趣的:(洛谷 P1063 能量项链 & [NOIP2006提高组](区间dp,断环为链))