傳送門:https://www.luogu.org/problem/P1063c++
從今之後區間dp應該沒問題了spa
很容易想到和石子合併同樣的操做,首先破環爲鏈,將環斷開變成兩倍,題中的例子就會變成這code
以後設dp[ l ][ r ],分別枚舉起點 i 和長度 k 以及分割點 xblog
由此可得狀態轉移方程:dp[l][r]=max(dp[l][r],dp[l][i]+dp[i+1][r]+num[l]*num[i+1]*num[r+1])get
代碼以下it
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int num[109]; 5 long long ans; 6 long long dp[209][209]; 7 inline int kd() 8 { 9 int x=0,f=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();} 12 return x*f; 13 } 14 int main() 15 { 16 n=kd(); 17 for(int i=1;i<=n;i++) 18 { 19 num[i]=kd(); 20 num[i+n]=num[i];//破環爲鏈 21 } 22 for(int k=2;k<=n;k++)//枚舉合併長度 23 { 24 for(int l=1;l+k-1/*終點小於長度*/<=2*n;l++)//枚舉起點 25 { 26 int r=l+k-1;//算出終點 27 for(int i=l;i<=r-1;i++)//枚舉分割點 28 { 29 dp[l][r]=max(dp[l][r],dp[l][i]+dp[i+1][r]/*兩段原來的最大值*/+num[l]*num[i+1]*num[r+1]/*合併產生的值*/); 30 } 31 } 32 } 33 for(int i=1;i<=n;i++) 34 { 35 ans=max(ans,dp[i][i+n-1]);//枚舉出最大值 36 } 37 cout<<ans; 38 }