题目链接:https://vjudge.net/problem/51Nod-1021

题意

N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。

例如:1 2 3 4 ,有不少合并方法

1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。

输入

第1行:N(2 <= N <= 100)

第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)

输出

输出最小合并代价

样例输入

4
1
2
3
4

样例输出

19

题解:

这道题目如果其实我自己接触的时候还是很早的,我很早很早之前就在一场比赛当中接触到了这道题目,那是很久很久之前的一个春天,我大一的时候的一场校赛中,我唯一没有做出来TLE的题,因为当时还不知道记忆化搜索这个概念。

所以我当时的解法是用的dfs,没有使用记忆化进行剪枝。

这里的记忆化搜索其实可以对应动态规划的状态转移方程。

首先我们可以回到这道题目里面来,可以看到:

区间 [1..N] 经过 N-1 次合并会获得最终的一个数,那么在经过 N-2 次合并的时候是会还剩2个数的,而且这两个数肯定还是连续的 a[i]a[i+1] ,所以,如果我们设 dp[i][j] 表示合并区间 [i,j] 的最小代价,那么:

dp[i][j] = min(dp[i][k] + dp[k+1][j]) + sum(i,j) , 其中k=i,i+1,...,j-1

这里的 sum(i,j) 表示 a[i]+a[i+1]+...+a[j]

那么 dp[i][j] 怎么求呢,我们可以通过定义一个函数 dfs(i,j) 来求得,但是可以通过记忆化搜索进行剪枝优化,其实就是写DP的时候记录的一些中间结果对应的重叠子问题。

代码如下(这个代码我没有验证过正确性,不过应该是没有问题的,主要理解他的思想):

#include <iostream>
using namespace std; const int maxn = 1010; int n, a[maxn], dp[maxn][maxn], sum[maxn]; int dfs(int l, int r) {
if (l == r) return 0;
if (l+1 == r) {
return dp[l][r] = a[l] + a[r];
}
if (dp[l][r])
return dp[l][r];
for (int i = l; i < r; i ++) {
int tmp = dfs(l,i) + dfs(i+1, r) + sum[r] - sum[l-1];
if (!dp[l][r]) dp[l][r] = tmp;
else dp[l][r] = min(dp[l][r], tmp);
}
return dp[l][r];
} int main() {
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
sum[i] = sum[i-1] + a[i];
}
cout << dfs(1, n) << endl;
return 0;
}

石子合并 区间DP模板题的更多相关文章

  1. 石子合并 区间dp模板

    题意:中文题 Description 在操场上沿一直线排列着 n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.允许在第一次合 ...

  2. HDU4632 Poj2955 括号匹配 整数划分 P1880 [NOI1995]石子合并 区间DP总结

    题意:给定一个字符串 输出回文子序列的个数    一个字符也算一个回文 很明显的区间dp  就是要往区间小的压缩! #include<bits/stdc++.h> using namesp ...

  3. 石子合并——区间dp

    石子合并(3种变形) <1> 题目: 有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为改次合并的得分, ...

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

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

  5. HRBUST - 1818 石子合并 区间dp入门

    有点理解了进阶指南上说的”阶段,状态和决策“ /* 区间dp的基础题: 以区间长度[2,n]为阶段,枚举该长度的区间,状态dp[l][r]表示合并区间[l,r]的最小费用 状态转移方程dp[l][r] ...

  6. [nyoj737]石子归并(区间dp入门题)

    题意:有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...

  7. 洛谷 P1080 石子合并 ( 区间DP )

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

  8. 洛谷P1880 石子合并(环形石子合并 区间DP)

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

  9. HDU 3506 (环形石子合并)区间dp+四边形优化

    Monkey Party Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Tot ...

随机推荐

  1. 4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(远程升级WIFI内部程序)

    https://www.cnblogs.com/yangfengwu/p/10360618.html 演示视频: https://www.bilibili.com/video/av54894356/ ...

  2. vue vue-cli中引入全局less变量的方式

    我们经常用less定义一些全局变量,比如主题的颜色,为了避免在每个组件中引用我首先尝试放在main.js中,发现并不起作用... 先看vue-cli2.x 版本如何解决 1.安装; npm insta ...

  3. service 与 log日志

    service 初始化执行环境变量PATH和TERM PATH=/sbin:/usr/sbin:/bin:/usr/bin TERM,为显示外设的值,一般为xterm 执行/etc/init.d/目录 ...

  4. gdb tui设置默认窗口高度

    gdb -p 12999 -tui 先显示win信息(输入:info win) 显示如下: SRC (35 lines) <has focus> CMD (17 lines) 我们要改的是 ...

  5. [HackTheBox]WEB题目

    0x01 [50 Points] I know Mag1k 问题描述: Can you get to the profile page of the admin? 访问分配的地址,是一个带注册的登入页 ...

  6. iframe中用到的例子

    <view:qrytr>         <view:qrytd colspan="4">     <iframe id="ccbl&quo ...

  7. 4、vueJs基础知识04

    简单的目录结构: |-index.html |-main.js 入口文件 |-App.vue vue文件(组件),官方推荐命名法(首字母大写) |-components      组件存放的文件夹 | ...

  8. Spring mybatis thymeleaf 基础操作,实现数据展示,修改,删除,查询

    目录结构如图 index.html <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thyme ...

  9. 第十一周助教工作总结——NWNU李泓毅

    助教博客链接:https://www.cnblogs.com/NWNU-LHY/ 本次作业的要求:原型设计:https://www.cnblogs.com/nwnu-daizh/p/10761596. ...

  10. SQL学习笔记(二)

    连接查询 数据准备 例1:查询学生信息及学生的成绩 等值连接 此方法会产生笛卡尔积,生成的记录总数=表1的总数*表2的总数,会产生临时表 内连接 select * from 表1 inner join ...