【题解】分离与合体 [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]的更多相关文章

  1. LOJ P10151 分离与合体 题解

    Analysis 区间dp+记录路径 用dfs倒着找倒数第几次合并 #include<iostream> #include<cstdio> #include<cstrin ...

  2. 信奥赛一本通1573:分离与合体C++分离与合体

    题目链接 #include<cstdio> #include<algorithm> using namespace std; int dp[305][305]={},jojo[ ...

  3. LOJ 一本通一句话题解系列:

    第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...

  4. 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& ...

  5. 动态规划 之 区间DP练习

    前言 \(Loj\) 放上了那么多<信息学奥赛一本通>上的题(虽然我并没有这本书),我要给它点一个大大的赞 ^_^ 以后分类刷题不愁啦! 正文 那就一道道说吧. 石子合并 将 \(n\) ...

  6. 2020.7.19 区间dp阶段测试

    打崩了-- 事先说明,今天没有很在状态,所以题解就直接写在代码注释里的,非常抱歉 T1 颜色联通块 此题有争议,建议跳过 题目描述 N 个方块排成一排,第 i 个颜色为 Ci .定义一个颜色联通块 [ ...

  7. 2020.7.19 区间 dp 阶段测试

    打崩了-- 事先说明,今天没有很在状态,所以题解就直接写在代码注释里的,非常抱歉 T1 颜色联通块 此题有争议,建议跳过 题目描述 N 个方块排成一排,第 i 个颜色为 Ci .定义一个颜色联通块 [ ...

  8. loj题目总览

    --DavidJing提供技术支持 现将今年7月份之前必须刷完的题目列举 完成度[23/34] [178/250] 第 1 章 贪心算法 √ [11/11] #10000 「一本通 1.1 例 1」活 ...

  9. CSU训练分类

    √√第一部分 基础算法(#10023 除外) 第 1 章 贪心算法 √√#10000 「一本通 1.1 例 1」活动安排 √√#10001 「一本通 1.1 例 2」种树 √√#10002 「一本通 ...

随机推荐

  1. android studio学习----Failed to resolve: com.android.support:design:22.1.1

    这个目前好像没有合适的办法,唯一可行的就是 点击那个提示  进行SDK Manager下载就可以了 但是天朝的网啊,我试了很多次,突然的可以下载,运气啊 类似这一系列问题解决办法就是  重新更新SDK ...

  2. 安恒Red Team 内部红蓝对抗框架

    0x00  准备钓鱼攻击(从公开资源) 1.常见的红队攻击向量和技术   2.常见的蓝队侦查和预防控制 0x02 发送钓鱼邮件(到目标组织员工邮箱地址) 1.常见的红队攻击向量和技术   2.常见的蓝 ...

  3. 微信小程序开发--flex详细解读

    一.结构:flex布局 是由一个大的容器加上多个子元素组成. <view class="container"> <view </view> <v ...

  4. 简要分析一下java中线程的生命周期

    面试题:您了解线程吗?简单叙述一下线程的生命周期? 答:之前学过一些有关于线程方面的知识,并且在编写代码的过程中还是要经常考虑线程,所以,我对线程还是了解一点的. 首先,创建一个线程,线程进入初始状态 ...

  5. (原)堆叠hourglass网络

    转载请注明出处: https://www.cnblogs.com/darkknightzh/p/11486185.html 论文: https://arxiv.org/abs/1603.06937 官 ...

  6. 安装php源码包内的扩展

    本地环境 PHP 7.0.4 (cli) (built: Mar 13 2016 21:50:22) ( NTS ) 安装 进入源码包中的ext文件夹中 [root@test etc]# cd /us ...

  7. django迁移脚本

    执行migrate报错的解决办法: 想知道migrate为什么报错,需要先了解migrate到底做了什么事情 migrate做了什么事情? 1.将相关的迁移脚本翻译成sql语句,然后在数据库中执行 2 ...

  8. Linux shell 函数应用示例01

    函数Function的使用 定义函数 (1) 函数名称() {     ...     ... } (2) function 函数名称{     ...     ... } 调用函数         ...

  9. tf.variable_scope()和tf.name_scope()

    1.tf.variable_scope 功能:tf.variable_scope可以让不同命名空间中的变量取相同的名字,无论tf.get_variable或者tf.Variable生成的变量 Tens ...

  10. C#使用Xamarin开发移动应用 ---- 系列文章

    C#使用Xamarin开发移动应用 C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.) C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练, ...