能量项链
(动态规划不好..我从头学..)
(动态规划很暴力的感觉,,,只要暴力就完了?母鸡唉)
题解
区间动规
重点就是将整体划分为区间,小区间之间合并获得大区间
状态转移方程的推导如下
一、将珠子划分为两个珠子一个区间时,这个区间的能量=左边珠子*右边珠子*右边珠子的下一个珠子
二、区间包含3个珠子,可以是左边单个珠子的区间+右边两珠子的区间,或者左边两珠子的区间右边+单个珠子的区间
即,先合并两个珠子的区间,释放能量,加上单个珠子区间的能量(单个珠子没有能量。。)
Energy=max(两个珠子的区间的能量+单个珠子区间的能量,单个珠子的区间的能量+两个珠子的区间的能量 )
三、继续推4个珠子的区间,5个珠子的区间。
于是可以得到方程:Energy=max(不操作的能量,左区间合并后的能量+右区间合并后的能量+两区间合并产生能量)
两区间合并后产生的能量=左区间第一个珠子*右区间第一个珠子*总区间后面的一个珠子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define ll long long using namespace std; inline int read() { int sum = 0,p = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') p = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (sum *= 10) += ch - '0'; ch = getchar(); } return sum * p; } const int N = 109; ll n,val[N * 2]; ll dp[N * N][N * N],ans; int main() { n = read(); for(int i = 1; i <= n; i++) { val[i] = read(); val[i + n] = val[i]; } for(int i = 2; i <= 2 * n; i++) { for(int j = i - 1; j >= 1 && i - j < n; j--) { for(int k = j; k < i; k++) dp[j][i] = max(dp[j][i],dp[j][k] + dp[k + 1][i] + val[j] * val[k +1] * val[i + 1]); ans = max(ans,dp[j][i]); } } printf("%lld\n",ans); return 0; }
(抄题解快乐...)