c_aw_能量项链(破环成链)

对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。
因为只有这样,通过吸盘(吸盘是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)\)
posted @ 2020-09-13 09:59  童年の波鞋  阅读(167)  评论(0编辑  收藏  举报