TA的每日心情 | 衰 7 小时前 |
---|
签到天数: 35 天 [LV.5]常住居民I
注册会员

- 积分
- 64
|
一、问题背景与理解能量项链问题描述了一个环形排列的珠子序列,每个珠子有头尾标记。通过特定的聚合操作,相邻珠子可以合并并释放能量。我们的目标是找到使总能量最大的聚合顺序。这个问题本质上是一个环形区间动态规划问题,与矩阵连乘问题类似但更具挑战性。 二、算法核心思想环形问题线性化:将原 数组复制一份接在后面,转化为线性问题处理 区间DP定义:dp [j]表示合并第i到第j颗珠子能获得的最大能量 状态转移方程:dp [j] = max(dp[k] + dp[k+1][j] + arr*arr[k+1]*arr[j+1]),其中k为分割点
三、实现详解四、代码实现
- #include <iostream>
- #include <vector>
- #include <algorithm>
- using namespACe std;
- int main() {
- int n;
- cin >> n;
- vector<int> nums(n);
- for(int i = 0; i < n; ++i) {
- cin >> nums[i];
- }
-
- // 环形问题转化为线性问题:将数组复制一份接在后面
- vector<int> arr(nums.begin(), nums.end());
- arr.insert(arr.end(), nums.begin(), nums.end());
-
- // dp[i][j]表示合并i到j颗珠子的最大能量
- vector<vector<int>> dp(2*n, vector<int>(2*n, 0));
-
- // 区间DP:枚举区间长度
- for(int len = 2; len <= n; ++len) {
- // 枚举区间起点
- for(int i = 0; i + len - 1 < 2*n; ++i) {
- int j = i + len - 1; // 区间终点
- // 枚举分割点k
- for(int k = i; k < j; ++k) {
- // 状态转移方程:dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j] + arr[i]*arr[k+1]*arr[j+1])
- dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j] + arr[i]*arr[k+1]*arr[j+1]);
- }
- }
- }
-
- // 找出所有长度为n的区间中的最大值
- int res = 0;
- for(int i = 0; i < n; ++i) {
- res = max(res, dp[i][i+n-1]);
- }
- cout << res << endl;
-
- return 0;
- }
复制代码
五、常见错误与调试技巧忘记处理环形结构,直接当作线性问题处理 区间长度枚举范围错误(应为2到n) 分割点k的范围设置不正确 结果提取时没有考虑所有可能的起点
六、优化方向来源:牛客AB52能量项链问题:环形区间DP的完美应用
|
|