一道区间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行为最大得分.

输入输出样例

输入 #1

4
4 5 9 4
输出 #1

43
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]的更多相关文章

  1. 【区间dp】- P1880 [NOI1995] 石子合并

    记录一下第一道ac的区间dp 题目:P1880 [NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码: #include <iostream> ...

  2. P1880 [NOI1995]石子合并[区间dp+四边形不等式优化]

    P1880 [NOI1995]石子合并 丢个地址就跑(关于四边形不等式复杂度是n方的证明) 嗯所以这题利用决策的单调性来减少k断点的枚举次数.具体看lyd书.这部分很生疏,但是我还是选择先不管了. # ...

  3. 洛谷 P1880 [NOI1995]石子合并 题解

    P1880 [NOI1995]石子合并 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试 ...

  4. 区间DP小结 及例题分析:P1880 [NOI1995]石子合并,P1063 能量项链

    区间类动态规划 一.基本概念 区间类动态规划是线性动态规划的拓展,它在分阶段划分问题时,与阶段中元素出现的顺序和由前一阶段的那些元素合并而来由很大的关系.例如状态f [ i ][ j ],它表示以已合 ...

  5. P1880 [NOI1995]石子合并 区间dp

    P1880 [NOI1995]石子合并 #include <bits/stdc++.h> using namespace std; ; const int inf = 0x3f3f3f3f ...

  6. [LUOGU] P1880 [NOI1995]石子合并

    题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...

  7. 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并

    洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...

  8. [洛谷P1880][NOI1995]石子合并

    区间DP模板题 区间DP模板Code: ;len<=n;len++) { ;i<=*n-;i++) //区间左端点 { ; //区间右端点 for(int k=i;k<j;k++) ...

  9. 洛谷 P1880 [NOI1995] 石子合并(区间DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合 ...

随机推荐

  1. VR中的Redirection

    在虚拟现实(Virtual Reality,VR)中,很重要的一点就是用户的在虚拟环境中的漫游(navigation).除了固定视点的VR电影,一般的VR应用,特别是游戏或者其他交互式的应用,都会依赖 ...

  2. VR应用评测 - Google Spotlight Story: Sonaria

    Google Spotlight Story: Sonaria 一个5min左右的VR小电影,坐姿观看,但是用户其实可以移动+旋转视角.画面很抽象,所有的物体都由基本的单色几何形状组成,主角是两个一公 ...

  3. Kafka 学习笔记之 ZooKeeper作用

    Kafka使用ZooKeeper 配置管理 Leader Election 服务发现 首先进入ZooKeeper客户端: ls / 可以看到有以下节点: 查看Topic 配置信息:体现了ZooKeep ...

  4. charles抓包小程序

    charles抓包小程序: 原理呢,简单理解,通过charles开代理,然后手工wifi设置代理上网. 但是要做一些准备:手机要安装charles 证书. 注意的是安卓和ios有区别:目前安卓7.0版 ...

  5. java中不创建使用第三方变量,交换两个数的值

    1.直接使用算术运算法交换 先把两个数的和赋值给其中一个,然后做减法.例如num1=num1+num2; 此时num2(交换之后)就等于num1减去num2:废话不多说,直接上代码 public cl ...

  6. js常用正则整理

    个人博客: http://mcchen.club //校验是否全由数字组成 function isDigit(s) { var patrn=/^[0-9]{1,20}$/; if (!patrn.ex ...

  7. 如何在github上下载单个文件夹?

    前言:在查看源码的过程中,相信很多人都像我一样,遇到某个公司或个人的repository是几个项目的集合整理,而我只要其中某个项目文件夹.那不依赖其他软件,怎么通过git去下载呢??? 下面直接给个例 ...

  8. 解决window.onload延迟加载问题

    window.onload方法,表示当页面所有的元素都加载完毕,并且所有要请求的资源也加载完毕才触发执行function这个匿名函数里边的具体内容.这样肯定保证了代码在domReady之后执行.使用w ...

  9. ubuntu使用uwsgi+nginx部署django

    ls -lha export WORKON_HOME=~/venv source /usr/local/bin/vitualenvwrapper.sh VIRTUALENVWRAPPER_PYTHON ...

  10. python selenium鼠标滑动操作

    先安装pyautogui: pip install pyautogui #coding=utf-8 import pyautogui from selenium import webdriver fr ...