石子合并问题 GarsiaWachs算法

目录引入

一个较为朴素的算法

GarsiaWachs算法

引入

在一个操场上摆放着一排 \(N\) 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的 \(2\) 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

试设计一个算法,计算出将 \(N\) 堆石子合并成一堆的最小得分。

数据范围 \(n \le 4e4\)

一个较为朴素的算法

不是暴力

按照区间DP的思路来做

设 \(f_{i, j}\) 表示区间 \([i, j]\) 合并的最小得分,枚举一个端点 \(k\),那么有转移方程:(其中 \(a\) 数组是预处理后的前缀和)

\[f_{i, j} = \min \{ f_{i, j}, f_{i, k} + f_{k + 1, j} + a_j - a_{i - 1} \}

\]

注意 \(i\) 要倒序枚举,\(j\) 要正序枚举

答案就是 \(f_{1, n}\)

时间复杂度: \(O(n^3)\);空间复杂度:\(O(n^2)\)

Code

/*

Work by: Suzt_ilymics

Knowledge:

Time: O()

*/

#includeiostream

#includecstdio

#includecstring

#includealgorithm

#define LL long long

#define orz cout"lkp AK IOI!"endl

using namespace std;

const int MAXN = 22335;

const int INF = 1e9+7;

const int mod = 1e9+7;

int n;

int a[MAXN];

int f[MAXN][MAXN];

int read(){

int s = 0, f = 0;

char ch = getchar();

while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();

while(isdigit(ch)) s = (s 1) + (s 3) + ch - '0' , ch = getchar();

return f -s : s;

}

int main()

{

n = read();

for(int i = 1; i = n; ++i) a[i] = read() + a[i - 1];

for(int i = n; i = 1; --i){

for(int j = i; j = n; ++j){

if(i == j) continue;

f[i][j] = INF;

for(int k = i; k j; ++k) f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + a[j] - a[i - 1]);

}

}

printf("%d\n", f[1][n]);

return 0;

}

GarsiaWachs算法

发现数据范围太大了,上面的算法已经不能满足我们的需求,这里有一种优化算法,专门用来解决石子问题

每次操作,从前向后找一个最小的 \(k\),使其满足 \(a_{k - 1} \le a_{k + 1}\),然后合并 \(a_{k - 1}\) 和 \(a_k\)

从 \(k\) 开始向前找到第一个 \(j\) 使得 \(a_j a_{k - 1} + a_k\),并将合并后的新值插入位置 \(j\) 后面

进行 \(n - 1\) 次结束,在合并过程中统计答案即可

时间复杂度:\(O(n^2)\);空间复杂度:\(O(n)\)

正确性证明:作为一个OI,会应用就好啦,其实是我不会

Code

/*

Work by: Suzt_ilymics

Knowledge:

Time: O()

*/

#includeiostream

#includecstdio

#includecstring

#includealgorithm

#includevector

#define LL long long

#define orz cout"lkp AK IOI!"endl

using namespace std;

const int MAXN = 1e5+5;

const int INF = 1e9+7;

const int mod = 1e9+7;

LL n, ans = 0;

vectorint a;

int read(){

int s = 0, f = 0;

char ch = getchar();

while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();

while(isdigit(ch)) s = (s 1) + (s 3) + ch - '0' , ch = getchar();

return f -s : s;

}

int merge(){//GarsiaWachs算法

int k = a.size() - 2;

for(int i = 0; i a.size() - 2; ++i)

if(a[i] = a[i + 2]){

k = i; break;

}

int sum = a[k] + a[k + 1];

a.erase(a.begin() + k);

a.erase(a.begin() + k);

int inst = -1;

for(int i = k - 1; i = 0; --i)

if(a[i] sum){

inst = i; break;

}

a.insert(a.begin() + inst + 1, sum);

return sum;

}

int main()

{

n = read();

for(int i = 1; i = n; ++i) a.push_back(read());

for(int i = 1; i n; ++i) ans += merge();

printf("%lld", ans);

return 0;

}

石子合并问题 GarsiaWachs算法 相关文章

图解算法——合并k个排序列表(Merge k Sorted Lists)

1. 题目描述 You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. Merge all the linked-lists into one sorted linked-list and return it. 翻译: 给定一个 链表长度为k 的链表 数组 ,每个链表按 升序 排序

three.js中,绑定 mouseup 和 mousedown 事件不起作用/使用three.js实现点谁谁变红,已解决鼠标选不到目标问题

先检查一下你是否使用了 OrbitControls 如果使用了,同时想要添加点击事件,给物体模型添加点击事件,例如添加点到谁,谁就红 代码如下: // 点击功能let raycaster = nulllet instersected = nulllet mouse = nulllet useClick = false/** * 打开addClick函

第39天学习打卡(多线程 Thread Runnable 初始并发问题 Callable )

多线程详解 01线程简介 Process与Thread 程序:是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。 进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位。 通常在一个进程中可以包含若干个线程,当然一个进程中

Ubuntu下SystemTap的安装问题解决记录

SystemTap的安装方式: 一.直接通过apt-get安装 sudo apt-get install systemtap 二.通过安装包下载 $ sudo apt-get install build-essential$ sudo apt-get install gettext$ sudo apt-get install elfutils$ sudo apt-get install libdw-dev$ wget https:/

【剑指Offer-15】二进制中1的个数

问题 请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。 示例 输入: 00000000000000000000000000001011 输出: 3 解释: 输入的二进制串

C++求快速幂

“快速幂”被归结为一个a的b次方对m取余的问题,即 a b % m 问题的关键在于怎么更快地求得a b ,直观的做法是用b次循环去累乘a,时间复杂度是O(b)。而“快速幂”,又成为“二分幂”,通过二分的思想能在O(log b )的复杂度内求得a b 。 如果次数b是奇数,则a

01背包问题理解动态规划算法

一.动态规划算法 简单理解:在一些分治算法解决的问题中,需要将较大规模的问题转化为较小规模的问题,往往会用到递归。但是在一些问题中,递归的小问题被多次重复运算,浪费了性能,因此可以使用数组或者其他合适的方式将运算过的小规模问题的结果记录下来

使用Python批量合并文件夹下.csv数据

实现目标:一个文件夹下包括n个.csv数据文件,想将后缀为ts.csv的文件与对应数字的.csv文件进行合并 此图为wf.csv文件中的数据格式,ts.csv文件是与此文件等行数的一列数据,将此列数据添加到已有18列数据的后面,完成数据合并操作 代码如下: import pandas

【剑指Offer-13】机器人的运动范围

问题 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格

类似jar文件使用java无法打开问题

## 原因我一个彩笔在ctfhub,想对图片进行分割,拼接等操作,需要用到**Stegsolve**但是安装了java环境的我无法打开,经过校友的3、4次卸载安装还是没有让这个文件打开。。。(当然选择了正确的应用程序打开方式,环境变量也试了,就是打不开)命令窗口输入j

石子合并问题java,石子合并问题 GarsiaWachs算法相关推荐

  1. GarsiaWachs算法:石子归并问题

    1023 石子归并 V3 基准时间限制:2 秒 空间限制:131072 KB 分值: 320 难度:7级算法题  收藏  关注 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2 ...

  2. Java数据结构第一讲-排序算法

    常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构) 数据结构和算法作为程序员的基本功,一定得稳扎稳打的学习,我们常见的框架底层就是各类数据 ...

  3. 石子合并(GarsiaWachs算法)

    对于石子合并问题,有一个最好的算法,那就是GarsiaWachs算法.时间复杂度为O(n^2). 它的步骤如下: 设序列是stone[],从左往右,找一个满足stone[k-1] <= ston ...

  4. 石子合并的GarsiaWachs算法

    石子合并的GarsiaWachs算法 2010-07-28 18:55:51|  分类: 程序 |字号 订阅 石子合并(每次合并相邻的两堆石子,代价为这两堆石子的重量和,把一排石子合并为一堆,求最小代 ...

  5. 【BZOJ 3229】 3229: [Sdoi2008]石子合并 (GarsiaWachs算法)

    3229: [Sdoi2008]石子合并 Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合 ...

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

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

  7. 有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力

    有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力 典型的贪心题,即每次取出数量最少的两堆石子合并. 举个例子来说,假如有5堆石子,石 ...

  8. java怎么做沙子合并_dp之沙子合并 环形沙子合并 沙子合并加强 沙子三兄弟的故事...

    沙子合并加强 沙子合并问题 问题描述:设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=2000).每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆,每次只能合并 ...

  9. java jtable 单元格合并_JTable 单元格合并 【转】

    最近,我为了做一个管理系统,需要用到合并JTable的单元格.查找了很多资料,终于简单的实现了.现在把代码共享出来,希望对大家有用. 本程序主要实现行的合并,列的合并大家可以根据下面的代码修改. CM ...

最新文章

  1. Thinkpad产品预装Win7系统一键恢复方法介绍
  2. 调查内存泄漏第2部分–分析问题
  3. UVA1583 Digit Generator
  4. js设计模式之Constructor(构造器)
  5. 分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
  6. linux 分区 flags,linux磁盘分区
  7. 博客园博客美化相关文章目录
  8. 《Photoshop修饰与合成专业技法》—第1章快速选择工具和调整边缘
  9. 先查出已知的 然后将未知的当做 having里面的条件
  10. 有关网页没有显示数据库的值的问题
  11. XtraBackUp 全量备份
  12. ThinkPHP自动匹配CP端移动端模板
  13. 功能测试————Siri
  14. 教你通过bigemap和geojson获取echarts精确到乡镇、街道的地图json数据
  15. hans wouters_Hans教学丨十大进阶长板平花招式
  16. JAVA多线程向kafka的topic各分区中写入本地数据
  17. Eclipse项目红叉:报错Description Resource Path Location Type Target runtime Apache Tomcat v8.0 is not defin
  18. 债券价格和到期收益率的关系_债券价格、到期收益率与票面利率之间的关系是什么?...
  19. 分析快、易操作的数据分析工具推荐
  20. TeamLab的介绍

热门文章

  1. php代码导入sql,php导入SQL文件(示例代码)
  2. servlet 源码分析
  3. break在matlab中的用法,求助这个算法运行的时候说错误: BREAK只能在FOR或WHile使用...
  4. 大数据和后端学习知识体系思维导图
  5. 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试
  6. C++ Websites
  7. GitHub---最简单的使用
  8. 数据结构--------------静态表的希尔排序
  9. machine learning for hacker记录(4) 智能邮箱(排序学习推荐系统)
  10. AspNet2.0页面生命周期