【题解】分离与合体 [Loj10151]
【题解】分离与合体 [Loj10151]
【题目描述】
给定一个长度为 \(n\) 的序列,如果从某个点 \(k\) 处将区间 \([l,r]\) 断开,划分为 \([l,k]\) 和 \([k+1,r]\),可以得到 \(a[k]*(a[l]+a[r])\) 的分数,要求最后要把区间划分到无法再分为止(即长度全为 \(1\)),并按照分离时间从前到后,区间从左到右的顺序输出所有划分点 \(k\) 。
【样例】
样例输入:
7
1 2 3 4 5 6 7
样例输出:
238
1 2 3 4 5 6
【数据范围】
\(20\%\) \(N \leqslant 10\)
\(40\%\) \(N \leqslant 50\)
\(100\%\) \(N \leqslant 300\)
【分析】
与经典区间 \(dp\) 题石子合并 \([NOI1995]\) \([P1880]\)非常相似,用 \(dp[l][r]\) 表示将 \([l,r]\) 这段区间彻底划分完所能获得的最大分数。
通常区间 \(dp\) 有两种大的方向:
\((1).\) 从小区间向大区间转移
\((2).\) 从大区间向小区间转移
这道题应采用 \((1)\) 更为合适。
按区间长度从小到大枚举所有区间 \([l,r]\),再枚举所有决策点 \(k \in[l,r-1]\),\(dp\) 方程为:
\(dp[l][r]=max\{(a[l]+a[r])*a[k] + dp[l][k] +dp[k+1][r] \}\)
那么再来看这无比诡异的输出。
区间最优决策点在 \(dp\) 的时候记录一下就可以,输出方式可以用队列来进行模拟,和 \(bfs\) 的过程类似。
另外要注意这里队列的两种写法会造成空间消耗的不同,
\((1).\) 从队首取出元素后判断是否为合法区间(即长度大于 \(1\) 才输出划分点)
\((2).\) 在入队前判断,仅让合法区间入队。
第二种只会在队列中加入 \(n-1\) 个合法区间(因为只会划分 \(n-1\) 次),而第一种会比第二种多加入 \(n\) 个长度为 \(1\) 的不合法区间,因此队列空间要开 \(2n\)。
时间复杂度为 \(O(n^3)\) 。
【Code】
#include<cstdio>
#define Re register int
const int N=303;
struct QAQ{int l,r;}Q[N];//空间要开够
int n,h=1,t,tmp,a[N],g[N][N],dp[N][N];
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
int main(){
in(n);
for(Re i=1;i<=n;++i)in(a[i]);
for(Re i=2;i<=n+1;++i)
for(Re l=1;l+i-1<=n;++l){
Re r=l+i-1;
for(Re k=l;k<r;++k)
if((tmp=dp[l][k]+dp[k+1][r]+a[k]*(a[l]+a[r]))>dp[l][r])dp[l][r]=tmp,g[l][r]=k;
}
printf("%d\n",dp[1][n]);
Q[++t]=(QAQ){1,n};
while(h<=t){
QAQ x=Q[h++];
Re l=x.l,r=x.r,k=g[l][r];
// if(l==r)continue;/*写法1.0*/
// if(!k)continue;/*写法1.1*/
printf("%d ",k);
// Q[++t]=(QAQ){l,k};/*写法1*/
// Q[++t]=(QAQ){k+1,r};/*写法1*/
if(l<k)Q[++t]=(QAQ){l,k};/*写法2*/
if(k+1<r)Q[++t]=(QAQ){k+1,r};/*写法2*/
}
}
【题解】分离与合体 [Loj10151]的更多相关文章
- LOJ P10151 分离与合体 题解
Analysis 区间dp+记录路径 用dfs倒着找倒数第几次合并 #include<iostream> #include<cstdio> #include<cstrin ...
- 信奥赛一本通1573:分离与合体C++分离与合体
题目链接 #include<cstdio> #include<algorithm> using namespace std; int dp[305][305]={},jojo[ ...
- LOJ 一本通一句话题解系列:
第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...
- YBT 5.1 区间类动态规划
题解在代码中 石子合并[loj 10147] /* dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) i<=k& ...
- 动态规划 之 区间DP练习
前言 \(Loj\) 放上了那么多<信息学奥赛一本通>上的题(虽然我并没有这本书),我要给它点一个大大的赞 ^_^ 以后分类刷题不愁啦! 正文 那就一道道说吧. 石子合并 将 \(n\) ...
- 2020.7.19 区间dp阶段测试
打崩了-- 事先说明,今天没有很在状态,所以题解就直接写在代码注释里的,非常抱歉 T1 颜色联通块 此题有争议,建议跳过 题目描述 N 个方块排成一排,第 i 个颜色为 Ci .定义一个颜色联通块 [ ...
- 2020.7.19 区间 dp 阶段测试
打崩了-- 事先说明,今天没有很在状态,所以题解就直接写在代码注释里的,非常抱歉 T1 颜色联通块 此题有争议,建议跳过 题目描述 N 个方块排成一排,第 i 个颜色为 Ci .定义一个颜色联通块 [ ...
- loj题目总览
--DavidJing提供技术支持 现将今年7月份之前必须刷完的题目列举 完成度[23/34] [178/250] 第 1 章 贪心算法 √ [11/11] #10000 「一本通 1.1 例 1」活 ...
- CSU训练分类
√√第一部分 基础算法(#10023 除外) 第 1 章 贪心算法 √√#10000 「一本通 1.1 例 1」活动安排 √√#10001 「一本通 1.1 例 2」种树 √√#10002 「一本通 ...
随机推荐
- IIS下配置Php+Mysql+zend的图文教程(完整版)
网上有很多关于PHP在IIS下配置的教程,但都是一些很理性化的东西,我从里面整理出来这个教程 发出来为了方便参考,,有什么问题也可以大家一起交流,,如果有什么不对的地方,请指正.. 下面的教程都是在w ...
- UNITY Serializer 序列化 横向对比
UNITY Serializer 序列化 横向对比 关于序列化,无论是.net还是unity自身都提供了一定保障.然而人总是吃着碗里想着锅里,跑去github挖个宝是常有的事.看看各家大佬的本事.最有 ...
- nginx实现tcp的反向代理
nginx不仅可以实现http的反向代理,同时也支持TCP的反向代理以SSH为例1.编译的时候需要加入--with-stream这个参数,以加载ngx_stream_core_module这个模块2 ...
- hdu1801 01翻转 贪心
题目描述: 对于给出的一个n*m的矩形,它由1和0构成,现在给你一个r*c的矩形空间可以选择,且可以选择无数次(被选中的范围内01翻转),要求问将这个01矩阵全部变成0的最少需要翻多少次,且如果无法实 ...
- JS里==和===区别
面试常问的一个基础问题 == 和 ===区别是什么? 这里简单描述下 "==="叫做严格运算符,"=="叫做相等运算符 而且 == 会对数据做隐式转换,而=== ...
- Latex 调整断字,连接符,取消断词/断字
latex使用了处理断字的算法去自动的找断字的地方,而且latex会调整单词间距,使得文章看起来不会显得疏密不一致.大多数情况下,这些算法都工作得很好.但是因为断字的算法是根据某种规则来处理单词的断字 ...
- 201871010107-公海瑜《面向对象程序设计(Java)》第四周学习总结
201871010107-公海瑜<面向对象程序设计(Java)>第四周学习总结 项目 ...
- 201671010447 杨露露 实验十四 团队项目评审&课程学习总结
项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十四 团队项目评审&课程学习总结 作业学习目标 总结这学期软件工程学习获得 一 ...
- PHP将图片转base64格式函数
base64的好处是什么?今天在跟小伙伴讨论这个问题,要是全站用Php把图片转为base64行不行? 1. 提升性能: 网页上的每一个图片,都是需要消耗一个 http 请求下载而来的, 图片的下载始终 ...
- CF308C-Sereja and Brackets-(线段树+括号匹配)
题意:给出一段括号,多次询问某个区间内能匹配多少括号. 题解:线段树,结构体三个属性,多余的左括号l,多余的右括号r,能够匹配的括号数val. 当前结点的val=左儿子的val+右儿子的val+min ...