元素共鸣:唤醒神之眼

描述

在提瓦特大陆上,有N座由原石构成的神秘石柱,它们依次排列,编号为1,2,3,…,N。每座石柱都蕴含着不同程度的元素能量,这种能量的强度可以用一个整数来量化。为了唤醒沉睡中的神之眼,冒险者们必须将这些原石石柱合而为一,释放出最强大的元素共鸣。

每次只能选择相邻的两座石柱进行合并,合并的过程中会释放出一定量的元素能量,其值等于这两座石柱能量值的总和。合并后,这两座石柱就会形成一座新的更大的石柱,而与这两座石柱原先相邻的石柱将与新形成的石柱相邻。不同的合并顺序会导致不同的总能量释放量。

冒险者们如何选择合并的顺序才能使释放的元素能量总量最小,以尽可能节约能量唤醒神之眼?

输入

第一行一个数N表示原石石柱的数量N。(1≤N≤300)

第二行N个数,表示每座石柱的元素能量值(均不超过1000)。

输出

输出一个整数,表示能量释放的最小总量。

输入样例 

4
1 3 5 2

输出样例

22

思路:区间dp

我们可以定义一个二维数组 dp,其中 dp[i][j] 表示合并第 i 到第 j 座石柱所释放的最小总能量。

假设我们要合并第 i 到第 j 座石柱,那么可以遍历所有可能的分割点 ki <= k < j),将其分为两部分 [i, k] 和 [k+1, j],然后递归地求解这两部分的最小能量释放量,并将其相加。最后再加上合并第 i 到第 j 座石柱所需要的能量,即 sum[i][j]。选取所有分割点中能量释放量最小的情况作为 dp[i][j] 的值。

最终答案即为 dp[1][N]

代码实现:

#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int stelae[305]={0};
int sum[305]={0};
class solution
{
public:
    void Dp(vector<vector<int>>& dp,int N)
    {
        // 动态规划求解最小能量释放量
        for (int len = 2; len <= N; ++len) {
            for (int i = 1; i <= N - len+1 ; ++i) {
                int j = i + len-1;
                dp[i][j] = INT_MAX;
                for (int k = i; k < j; ++k) {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);
                }
            }
        }
        cout<<dp[1][N]<<endl;
    }
};
int main() {
    int N;
    cin >> N;
    vector<vector<int>> dp(N + 1, vector<int>(N + 1, 0));
    // 读入每座石柱的能量值,并计算前缀和
    for (int i = 1; i <= N; ++i) {
        cin >> stelae[i];
        sum[i] = sum[i - 1] + stelae[i];
    }

    solution p;
    p.Dp(dp,N);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值