对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。
因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。
如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为 r,尾标记为 n,则聚合后释放的能量为 mrn(Mars单位),新产生的珠子的头标记为 m,尾标记为 n
需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。
例如:设N=4,4颗珠子的头标记与尾标记依次为(2,3) (3,5) (5,10) (10,2)。
我们用记号⊕表示两颗珠子的聚合操作,(j⊕k)表示第 j,k 两颗珠子聚合后所释放的能量。则
第4、1两颗珠子聚合后释放的能量为:(4⊕1)=1023=60。
这一串项链可以得到最优值的一个聚合顺序所释放的总能量为((4⊕1)⊕2)⊕3)= 1023+1035+10510=710。
输入样例:
4
2 3 5 10
输出样例:
710
方法一:区间dp
加以修饰的环形石子合并...
- 定义状态:
- f[l][r] 表示将区间[l,r] 这一段合并得到的最大能量值
- 思考初始化:
- f[l][r]=0
- 思考状态转移方程:
- f[l][r]=f[l][i]+f[i+1][r]+A[l]A[i]A[r]
- 思考输出:max(f[l][l+n]),l∈[1,n]
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=205;
ll f[N][N], A[N];
ll dfs(int l, int r) {
if (l>=r) return 0;
if (f[l][r]) return f[l][r];
ll t=0;
for (int i=l+1; i<r; i++) {
t=max(t, dfs(l,i)+dfs(i,r)+A[l]*A[i]*A[r]);
}
return f[l][r]=t;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
ll n, ans=0; cin>>n;
for (int i=1; i<=n; i++) cin>>A[i], A[i+n]=A[i];
for (int i=1; i<=n; i++) ans=max(ans, dfs(i, i+n));
cout << ans;
return 0;
}
复杂度分析
- Time:\(O(n^3)\),
- Space:\(O(n^2)\)