洛谷Oj-能量项链-区间DP
来源:互联网 发布:线性优化的最优解法 编辑:程序博客网 时间:2024/06/16 00:42
问题描述:
在Mars星球上,每个Mars人都随身佩带着一串能量项链。在项链上有N颗能量珠。能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(Mars单位),新产生的珠子的头标记为m,尾标记为n。
需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。
例如:设N=4,4颗珠子的头标记与尾标记依次为(2,3) (3,5) (5,10) (10,2)。我们用记号⊕表示两颗珠子的聚合操作,(j⊕k)表示第j,k两颗珠子聚合后所释放的能量。则第4、1两颗珠子聚合后释放的能量为:
(4⊕1)=10*2*3=60。
这一串项链可以得到最优值的一个聚合顺序所释放的总能量为
((4⊕1)⊕2)⊕3)=10*2*3+10*3*5+10*5*10=710。
AC代码(递推):
int a[300],dp[300][300];int main(){ int n; //输入 cin >> n; for(int i = 1; i <= n; ++i) { int t; scanf("%d",&t); a[i] = a[n + i] = t;//将环拆成链 } for(int i = 1; i <= n; ++i)//初始化,自己无法与自己合并,因此释放的能量为0(起思路清晰作用,实际上dp[i][i]的值本来就是0) dp[i][i] = 0; for(int l = 2; l <= n; ++l)//枚举区间长度 for(int i = 1; l + i - 1 <= 2 *n - 1; ++i)//枚举区间起点。注意i <= n错!!! { int j = l + i - 1;//计算区间终点 for(int k = i; k <= j - 1; ++k)//枚举区间内的点,作为分隔点 //计算释放出的能量是关键 dp[i][j] = max(dp[i][j],dp[i][k] + dp[k + 1][j] + a[i] * a[k + 1] * a[j + 1]); } int ans = -inf; for(int i = 1; i <= n; ++i)//找出最大值 ans = max(ans,dp[i][n + i - 1]); cout << ans << endl; return 0;}
AC代码(记忆化搜索):
int a[210],dp[210][210];int dfs(int i,int j){ if(dp[i][j])//直接返回 return dp[i][j]; if(i == j)//边界条件,自己无法和自己合并,因此释放的能量为0 return 0; for(int k = i; k <= j - 1; ++k)//以k为分隔点 dp[i][j] = max(dp[i][j],dfs(i,k) + dfs(k + 1,j) + a[i] * a[k + 1] * a[j + 1]);//记忆化 return dp[i][j];}int main(){ int n; //输入 cin >> n; for(int i = 1; i <= n; ++i) { int t; scanf("%d",&t); a[i] = a[n + i] = t;//将环拆成链 } int ans = -inf; for(int i = 1; i <= n; ++i) ans = max(ans,dfs(i,i + n - 1));//保证区间[i,i + n - 1]的长度为n cout << ans << endl; return 0;}
解决方法:
这道题是区间DP,乍一看会觉得和石子合并的问题很相似。
DP的模板好套,就是需要注意的细节很多。
比较难写的就是合并珠子释放能量的语句 a[i] * a[k + 1] * a[j + 1]
画图可得,两个大珠子是由区间内若干个小珠子合并而成的,又联系a[i]的意义,所以得出如上的公式
大区间的最优解由小区间的最优解得来,基于分治的思想,我们不断划分区间,直到区间内只有一个元素,枚举它们的组合,求得所有情况合并后的最优值。
通过小区间更新大区间,最终获得指定区间的最优值
dp[i][j]的含义是区间[i,j]内元素合并所获得的最大收益
区间DP大体框架如上代码
- 洛谷Oj-能量项链-区间DP
- codevs1154 能量项链(区间DP)
- [noip2006]能量项链 区间DP
- HZNU-能量项链【区间dp】
- Codevs1154[能量项链] 区间DP
- 区间DP NOIP2006 能量项链
- codevs1154 能量项链 区间dp
- 能量项链 (区间DP,环状)
- wikioi 1154 - 能量项链 (环形区间dp)
- Hrbustoj1376 能量项链 简单区间DP
- 【CODEVS 1154】能量项链(区间DP)
- 能量项链 hrbustoj 1376 区间dp
- noip2006 能量项链 (区间dp)
- zjnu 1182 能量项链(区间DP)
- nefu269 noip2006能量项链【区间dp 环】
- codevs 1154 能量项链(区间dp)
- Hrbust 1376 能量项链【区间dp】
- codevs 1048能量项链(区间DP)
- python:关于函数返回return的问题
- Android 在布局里去掉抬头标题栏
- Photon_创建工程添加MySql.data库_001
- 读《编译原理》第六章,中间代码生成
- HBase常用操作
- 洛谷Oj-能量项链-区间DP
- JEESZ-kafka消息服务平台实现
- qsort函数、sort函数
- iOS 11.0新功能
- 题(problem) (组合求方案数)
- 匹配两行,然后获取直到空行的一个段落
- IE8兼容canvas
- spring源码分析,重新认识spring四(回顾下上篇的问题,以及从spring 的常用模式开始)
- 32:行程长度编码