题目链接:http://www.hihocoder.com/problemset/problem/1636

题目描述

在中国古代神话中,盘古是时间第一个人并且开天辟地,它从混沌中醒来并把混沌分为天地。

刚开始地上是没有山的,只有满地的石头。

这里有 \(N\) 堆石头,标号为从 \(1\) 到 \(N\) 。盘古想要把它们合成一堆建造一座大山。如果某些堆石头的数量总和是 \(S\) ,盘古需要 \(S\) 秒才能把它们合成一堆,这新的一堆石头的数量就是 \(S\) 。

不幸的是,每一次盘古只能把连续的 \(L\) 到 \(R\) 堆石头合并成一堆。

盘古希望尽快把所有石头合成一堆。

你能帮帮他吗?如果没有解,则输出 \(0\) 。

解题思路

可以把合并所有石头的过程拆分成几个子步骤,首先合并连续的一些,然后再合并连续的一些,大区间的结果可以由小区间推出,所以就从小区间开始考虑,逐步推向大区间,可以用 dp[i][j][k] 表示区间 [i,j] 分成 k 堆得最小代价,对于固定的一个区间,肯定是取所有情况的最小值,最后答案是 dp[1][n][1] ,注意边界处理,包括刚开始的初始化。

然后就是代码处理中的一些细节了。

首先将所有的 f[i][j][k] 置为 INF

然后对于所有的初始状态(即 f[i][j][j-i+1] )都置为 \(0\) 。

因为区间 \([i,j]\) 内本身就有 \(j-i+1\) 个元素,所以这些元素本身就这么多堆,是不需要花费代价去划分的。这就是我所说的初始状态。

然后就是合并区间了,区间合并一般都是小区间开始合并到大区间,我们这里也不例外(记忆化搜索的话就得反着来了)。

对于一个区间 \([l,r]\) ,它要么是直接合并成一对,要么是若干个区间拼接到一起。所以我们这里分情况讨论:

直接合并

如果区间 \([l,r]\) 直接合并,那么合并成一对的最小代价应该是 \(f[l][r][1]\) 。

那么对于区间 \([l,r]\) ,我一定可以将其查分成两个区间 \([l,i]\) 和 \([i+1,r]\) ,其中坐区间有 \(j\) 个元素,右区间有 \(1\) 个元素,并且满足 \(L \le j+1 \le R\) 。

于是我们可以从 \(l \sim r-1\) 枚举 \(i\) ,从 \(L-1 \sim R-1\) 枚举 \(j\) ,

则 \(f[l][r][1] = \min(f[l][i][j]+f[i+1][r][1]) + sum[r] - sum[l-1]\) 。(这里 \(sum[r] - sum[l-1]\) 表示区间 \([l,r]\) 范围内的石子数量之和)

区间拼接

这里讲的区间拼接其实就是对于两个区间 \([l,j]\) 和 \([j+1,r]\) ,假设他们分别有 \(i-1\) 堆和 \(1\) 堆石子,那么这个区间总共有 \(i\) 堆石子。

区间拼接就不需要考虑合并了。

所以对于区间 \([l,r]\) 包含 \(i\) 堆石子的情况,它对应状态 \(f[l][r][i]\) ,那么它总能拆分成两个状态(\(f[l][j][i-1]\) 和 \(f[j+1][r][1]\) ,其中 \(l \le j \lt r\))的拼接。

可以推导出状态转移方程为: \(f[l][r][i] = min(f[l][j][i-1] + f[j+1][r][1])\) ,其中 \(2 \le i \le len,l \le j \lt r\) 。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
#define INF (1<<29)
const int maxn = 110;
int n, L, R, a[maxn], sum[maxn], f[maxn][maxn][maxn];
int main() {
while (~scanf("%d%d%d", &n, &L, &R)) {
for (int i = 1; i <= n; i ++) scanf("%d", a+i);
for (int i = 1; i <= n; i ++) sum[i] = sum[i-1] + a[i];
for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) for (int k = 1; k <= n; k ++) f[i][j][k] = INF;
for (int l = 1; l <= n; l ++) for (int r = l; r <= n; r ++) f[l][r][r-l+1] = 0;
for (int len = 1; len <= n; len ++) {
for (int l = 1; l+len-1 <= n; l ++) {
int r = l+len-1;
for (int i = l; i < r; i ++) {
for (int j = L-1; j < R; j ++) {
f[l][r][1] = min(f[l][r][1], f[l][i][j] + f[i+1][r][1] + sum[r] - sum[l-1]);
}
}
for (int i = 2; i < len; i ++) {
for (int j = l; j < r; j ++) {
f[l][r][i] = min(f[l][r][i], f[l][j][i-1] + f[j+1][r][1]);
}
}
}
}
if (f[1][n][1] == INF) puts("0");
else printf("%d\n", f[1][n][1]);
}
return 0;
}

2017 ACM-ICPC亚洲区域赛北京站J题 Pangu and Stones 题解 区间DP的更多相关文章

  1. 【2017 ICPC亚洲区域赛北京站 J】Pangu and Stones(区间dp)

    In Chinese mythology, Pangu is the first living being and the creator of the sky and the earth. He w ...

  2. 2015 ACM / ICPC 亚洲区域赛总结(长春站&北京站)

    队名:Unlimited Code Works(无尽编码)  队员:Wu.Wang.Zhou 先说一下队伍:Wu是大三学长:Wang高中noip省一:我最渣,去年来大学开始学的a+b,参加今年区域赛之 ...

  3. 【2016 ICPC亚洲区域赛北京站 E】What a Ridiculous Election(BFS预处理)

    Description In country Light Tower, a presidential election is going on. There are two candidates,   ...

  4. Digit sum (第 44 届 ACM/ICPC 亚洲区域赛(上海)网络赛)进制预处理水题

    131072K   A digit sum S_b(n)Sb​(n) is a sum of the base-bb digits of nn. Such as S_{10}(233) = 2 + 3 ...

  5. Known Notation括号匹配类问题(2014年ACM/ICPC 亚洲区域赛牡丹江)

    题意: 给你数字或 * 的串,你可以交换一个*和数字.在最前面添1.在一个地方插入*,问你使串满足入栈出栈的(RNP)运算法则. 思路: 引用:https://blog.csdn.net/u01158 ...

  6. 2014ACM/ICPC亚洲区域赛牡丹江站汇总

    球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...

  7. icpc 2017北京 J题 Pangu and Stones 区间DP

    #1636 : Pangu and Stones 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 In Chinese mythology, Pangu is the fi ...

  8. 【2017 ICPC亚洲区域赛沈阳站 K】Rabbits(思维)

    Problem Description Here N (N ≥ 3) rabbits are playing by the river. They are playing on a number li ...

  9. HDU - 6215 2017 ACM/ICPC Asia Regional Qingdao Online J - Brute Force Sorting

    Brute Force Sorting Time Limit: 1 Sec  Memory Limit: 128 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

随机推荐

  1. 模板—插头dp(Ural 1519 Formula 1)

    括号表示法: 据说比下一个要快而且灵活. #include<iostream> #include<cstring> #include<cstdio> #define ...

  2. SaltStack之用户账户管理

    在Salt.state中,user 模块是用来创建用户和管理用户设定的,用户可以被设置成 present 状态或者 absent 状态 注释: present:添加用户 absent   : 删除用户 ...

  3. 2018-8-10-WPF-如何在绑定失败异常

    title author date CreateTime categories WPF 如何在绑定失败异常 lindexi 2018-08-10 19:16:53 +0800 2018-05-17 1 ...

  4. NGINX比Apache的性能高是因为NGINX由C语言开发,而Apache由C++开发

    事实上,NGINX比Apache的性能高是因为NGINX由C语言开发,而Apache由C++开发.因此,NGINX效率大概是Apache的10倍左右

  5. Mule自带例子之stockquote

    1 配置效果图 2 配置文件 <?xml version="1.0" encoding="UTF-8"?> <mule version=&qu ...

  6. phpstorm 有的单词下有下划线,怎么去掉?

    settings -> Editor -> Colors & Fonts -> General ->Errors and Warnings然后你会看见下面的示例代码.点 ...

  7. dotnet core 2.1 使用阶梯编译

    在 dotnet core 2.1 可以使用阶梯编译的方法,从 dotnet framework 开始,在代码的所有方法在第一次进入的时候就需要使用 JIT 进行编译为本机的代码.可以看到代码是在第一 ...

  8. 【codeforces 766C】Mahmoud and a Message

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  9. python基础数据类型汇总

    list和dict 在循环一个列表和字典时,最好不要删除其中的元素,这样会使索引发生改变,从而报错! lis = [11, 22, 33, 44, 55] for i in range(len(lis ...

  10. 常用mime.types

    以下是从nginx配置文件mime.types中提取出的最常用的文件格式, 整理了下, 方便查看 类型 文件格式 default_type application/octet-stream - tex ...