本来算法使用MarkDown写,但是发现我们的MarkDown真的难用~

题目大意:

有n个珠子编号为1~n且首尾相接为环状,每一个珠子有头标记和尾标记,第i个珠子的尾标记是第i-1个珠子的头标记,第i个珠子的尾标记是第i+1个珠子的头标记;特别的,第n珠子的尾标记是第1个珠子的头标记。


解题思路:

假设有4个珠子,我们只看最后一次合并,一共有以下4种合并方式:

第一种:①+ ②③④

第二种:①②+ ③④

第三种:①②③+ ④

第四种:④①+ ②③

注意,我们只看最后一次合并,那么对于第一种中的②③④使用同样的方式可以分为②+③④、②③+④,其他的情况也类似。

这种思想其实就是区间DP的思路了。


但是这个题目是首尾相接呈环状的,怎么处理环状呢?对于这类环状问题,处理的方式就是:断环为链。简单来说就是,这个序列是1~n,在复制一个同样的放到n后面,那么序列就成1~2n了。


区间DP模板代码:

枚举区间长度len(2 ~ n)
    枚举区间起点i(1 ~ i+len-1<=2n)
        算出区间终点j = i+len-1
        枚举区间断点k(i <= k < j) 
            状态转移 注意事项:


ok,对于动态规划题目一定搞清楚三点:状态表示,初始状态,状态转移。(建议自己写动归的题目的时候先把这三点列出来再去写)

状态表示:dp[i][j]表示第i颗珠子到第j颗珠子聚合成一颗珠子后所释放的最大能量

初始状态:dp[i][i]=0,单独一个珠子无法释放能量

状态转移:dp[i][j] =  max{dp[i][k] + dp[k+1][j] + a[i]*a[k+1]*a[j+1]},i≤k<j,k为断点

注意:从第k个位置断开(i~k已经聚合成一个珠子且k+1~j也聚合成一个珠子,这个在状态转移的过程已经处理好了)左右两个珠子聚合得到的能量为:a[i]*a[k+1]*a[j+1]。


参考代码:

#include <iostream>
using namespace std;

int n, a[405], dp[405][405], ans; 

int main()
{
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
		a[i+n] = a[i];
	}
	for (int len = 2; len <= n; ++len)
		for (int i = 1; i + len - 1 <= 2*n; ++i)
		{
			int j = i + len - 1;
			for (int k = i; k < j; ++k)
				dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j] + a[i] * a[k+1] * a[j+1]);
		}
	for (int i = 1; i <= n; ++i)
		ans = max(ans, dp[i][i+n-1]);
	cout << ans << endl;
	return 0;
}
点赞(0)
 

0.0分

39 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 10 条评论

碇真嗣 10月前 回复TA
@灰太狼 确实哦
咖啡 2年前 回复TA
@灰太狼 你好,这个对答案并没有影响,因为是在复制数组之后的基础上考虑,出现2*n+1的这个情况其实已经在前面计算过了(这里数组不会出现溢出),这里最后一次计算也是重复计算,当然可以直接写成 < 2*n 也没有任何问题。感谢您提出问题。
灰太狼 2年前 回复TA
题主的代码似乎有些细节错误,从15和17行可以看出,j最大可以取2*n,但是19行出现了j+1,导致数据溢出,解决办法是可以将a数组里的数据由2*n扩展到3*n,但是题主的代码提交无任何问题,可能是测试数据不够全面导致
灰太狼 2年前 回复TA
@灰太狼 我这样想是错的,题主说的1234只是能量连环中的一小节,所以就只有4种
灰太狼 2年前 回复TA
1234珠子的最后一次合并不应该有6种吗,123+4,234+1,341+2,412+3,12+34,23+14?
4866 2年前 回复TA
收获良多
哦嘞嘞 2年前 回复TA
漂亮啊!
庞发月 3年前 回复TA
深受启发,十分感谢
LBD西瓜泥 3年前 回复TA
nice
验题君 3年前 回复TA
MD问题收到,已经转告RD并且扣一个鸡蛋