NOI1995 石子合并 [Luogu P1880]
一道区间dp的模板题,这里主要记一下dp时环形数据的处理。
简略版:方法一:枚举分开的位置,将圈化为链,因此要做n次。
方法二:将链重复两次,即做一个2n-1长度的链,其中第i(i<=n)堆石子与i+n堆相同。
对整个长链dp后,枚举(1, n), (2, n+1) ... (n, 2n-1),取最值即可。
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入格式
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入 #14
4 5 9 4输出 #143
54
由于只有相邻的石子才能被合成为一堆,因此在所有时刻的任意一堆石子(无论被合成了几次)都可以看做相邻几堆石子的和。即,均可以用一个闭区间[l, r]表示。
进行动态规划时,两堆石子的合并可以被看作两个区间的合并,即两个小区间的信息向一个大区间转移。
为处理环形数据,这里采用的方法是将数组arr重复两次,即arr[i+n] = arr[i](i<=n)。
设sum[i]为数组arr(重复后)的前缀和,dp1[i][j]、dp2[i][j]分别为第i堆至第j堆石子合并的得分最小值、最大值。
状态转移方程:
dp1[i][j] = min{dp1[i][k] + dp1[k+][j] + sum[j] - sum[i-]}
dp2[i][j] = max{dp2[i][k] + dp2[k+][j] + sum[j] - sum[i-]}
(i <= k <= j-)
注意初始化dp1[i][i] = INF,dp2[i][i] = 0。
代码实现后时间复杂度为O(8n3),相对与朴素的拆环方式(枚举断点做n次dp)的时间复杂度O(n4)在数据较大时有优势。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXN 300
using namespace std;
int dp1[MAXN][MAXN], dp2[MAXN][MAXN];
int arr[MAXN], sum[MAXN];
int n, ans_min = INF, ans_max = -;
void in_put(){
scanf("%d", &n);
for(int i=; i<=n; i++){
scanf("%d", &arr[i]);
arr[i+n] = arr[i];
}
}
void dp(){
for(int len=; len<=n; len++){
for(int i=; i<=*n; i++){
int end = i + len - ;
dp1[i][end] = INF, dp2[i][end] = -;
for(int j=i; j<end; j++){
dp1[i][end] = min(dp1[i][end], dp1[i][j] + dp1[j+][end]);
dp2[i][end] = max(dp2[i][end], dp2[i][j] + dp2[j+][end]);
}
dp1[i][end] += sum[end] - sum[i-];
dp2[i][end] += sum[end] - sum[i-];
}
}
for(int i=; i<=n; i++){
if(dp1[i][i+n-] < ans_min) ans_min = dp1[i][i+n-];
if(dp2[i][i+n-] > ans_max) ans_max = dp2[i][i+n-];
}
}
int main(){
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
in_put();
for(int i=; i<=n*; i++){
sum[i] = sum[i-] + arr[i];
dp1[i][i] = , dp2[i][i] = ;
}
dp();
printf("%d\n%d", ans_min, ans_max);
return ;
}
NOI1995 石子合并 [Luogu P1880]的更多相关文章
- 【区间dp】- P1880 [NOI1995] 石子合并
记录一下第一道ac的区间dp 题目:P1880 [NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码: #include <iostream> ...
- P1880 [NOI1995]石子合并[区间dp+四边形不等式优化]
P1880 [NOI1995]石子合并 丢个地址就跑(关于四边形不等式复杂度是n方的证明) 嗯所以这题利用决策的单调性来减少k断点的枚举次数.具体看lyd书.这部分很生疏,但是我还是选择先不管了. # ...
- 洛谷 P1880 [NOI1995]石子合并 题解
P1880 [NOI1995]石子合并 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试 ...
- 区间DP小结 及例题分析:P1880 [NOI1995]石子合并,P1063 能量项链
区间类动态规划 一.基本概念 区间类动态规划是线性动态规划的拓展,它在分阶段划分问题时,与阶段中元素出现的顺序和由前一阶段的那些元素合并而来由很大的关系.例如状态f [ i ][ j ],它表示以已合 ...
- P1880 [NOI1995]石子合并 区间dp
P1880 [NOI1995]石子合并 #include <bits/stdc++.h> using namespace std; ; const int inf = 0x3f3f3f3f ...
- [LUOGU] P1880 [NOI1995]石子合并
题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...
- 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并
洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...
- [洛谷P1880][NOI1995]石子合并
区间DP模板题 区间DP模板Code: ;len<=n;len++) { ;i<=*n-;i++) //区间左端点 { ; //区间右端点 for(int k=i;k<j;k++) ...
- 洛谷 P1880 [NOI1995] 石子合并(区间DP)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合 ...
随机推荐
- 织梦DEDE分类信息实现联动筛选(支持多条件多级选项)解决方案
发布时间:2017-03-25 来源:未知 浏览:404 关键词: 很多织梦建站的站长在做产品列表页的时候,产品分类多而且都是关联的,用户不能快速的找到自己需要的东西,很多情况下都需要用到筛选功能,织 ...
- 【转】ICMP协议
1.ICMP出现的原因 在IP通信中,经常有数据包到达不了对方的情况.原因是,在通信途中的某处的一个路由器由于不能处理所有的数据包,就将数据包一个一个丢弃了.或者,虽然到达了对方,但是由于搞错了端口号 ...
- Thinkphp5.0第四篇
删除数据 当前模型删除 $user=UserModel::get(1); if($user->delete()){return '删除成功';} else{return '删除失败';} 根据主 ...
- Vue入门教程 第三篇 (条件与循环)
v-if语法(条件) 符合条件时显示(渲染)某一元素. <div id="app"> <div v-if="ok"> <h1> ...
- ef core实现软删除
很多web程序一般的偶不会设计真的物理删除了. 基本上都是在在数据库加一个标记,就得当作已经删除了.同时在查询的时候,过滤已经标记删除的数据 ef core实现软删除是非常简单的,直接在OnModel ...
- css3——box-sizing属性
很多朋友们可能会疑惑,不知道box-sizing属性是有什么作用,自己也很少会用到,但是想必不少人在做网页布局的时候经常遇到一个问题就是我明明设置了父元素设置了假如是宽高500px,5个子元素左浮动设 ...
- 《深入理解Java虚拟机》-----第12章 Java内存模型与线程
概述 多任务处理在现代计算机操作系统中几乎已是一项必备的功能了.在许多情况下,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与它的存储和通信子系统速 ...
- USART_FLAG_TXE和USART_FLAG_TC
在串口数据发送操作中,代码一般是这样写的: void USART_SendByte(USART_TypeDef* USARTx, uint8_t Data) { while(USART_GetFlag ...
- web项目中登陆超时的功能实现(基于C#)
当我们登陆进网站后,中途去看别的东西,没有再与该网站的服务器交互,就会弹出一个js窗口,登陆超时请重新登陆,并跳转到登陆页面. 步骤1.实现原理,在web.config中配置session的超时时间, ...
- 如何巧妙地在基于 TCP Socket 的应用中实现用户注册功能?
通常,在基于TCP的应用中(比如我开源的GGTalk即时通信系统),当TCP连接建立之后,第一个请求就是登录请求,只有登录成功以后,服务器才会允许客户端进行其它性质的业务请求.但是,注册用户这个功能比 ...