所为区间DP,主要是把一个大区间拆分成几个小区间,先求小区间的最优值,然后合并起来求大区间的最优值。

区间DP最关键的就是满足最优子结构以及无后效性!!

例如像是石子合并和括号匹配这两类比较经典的模型。

一般的区间dp写法是:

    for(int len=;len<=n;len++)    //枚举区间长度
{
for(int i=;i<=(n<<)-len+;i++) //区间的左端点
{
int j=i+len-;
for(int s=i;s<j;s++)
{
//大区间与小区间的关系;
}
}
}

转移方程的推理:

首先,要计算合并的最大值、最小值,既然是动态规划,我们需要洞悉其中一些关联且确定的状态。

以下以最大值为例。

既然是最大值,那么求得的结果是否满足每一区间都是该区间所能达得到的的最大值?

显然是这样的。反证法:倘若有一个区间不是,那么换做该区间取得最大值的方案,最终结果将比原得分大。显然必定满足任意区间得分一定是该区间内的最大值。

这样我们可以定义状态f[i][j],表示i到j合并后的最大得分。其中1<=i<=j<=N。

既然这样,我们就需要将这一圈石子分割。很显然,我们需要枚举一个k,来作为这一圈石子的分割线。

这样我们就能得到状态转移方程:

$f[i][j] = max(f[i][k] + f[k+1][j] + d(i,j))$ 其中,1<=i<=<=k<j<=N。

d(i,j)表示从i到j石子个数的和,也就是合并的代价。

需要确定首尾指针,和枚举中间的断点,时间复杂度O(n3),虽然可以进一步利用什么四边形优化,在这里不做过探讨。

对于最简单的石子合并(成链状)来说,就是一个模板题,答案自然是dp[1][n]。

而对于呈环状的的来说则需要将数据复制一遍,答案为$max(dp[ i =(1-n) ][ i+n-1 ])$

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define LL long long
#define mod int(1e9+7)
#define wlz 1234567890
int n,ans1,ans2;
int a[],sum[],f1[][],f2[][];
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
a[i+n]=a[i];
}
for(int i=;i<=n*;i++)
{
sum[i]=sum[i-]+a[i];
f1[i][i]=f2[i][i]=;
}
for(int len=;len<=n;len++)
{
for(int i=;i<=(n<<)-len+;i++)
{
int j=i+len-;
f1[i][j]=wlz;
for(int s=i;s<j;s++)
{
f1[i][j]=min(f1[i][j],f1[i][s]+f1[s+][j]);
f2[i][j]=max(f2[i][j],f2[i][s]+f2[s+][j]);
}
f1[i][j]+=(sum[j]-sum[i-]);
f2[i][j]+=(sum[j]-sum[i-]);
}
}
ans1=wlz;
for(int i=;i<=n;i++)
{
ans1=min(ans1,f1[i][i+n-]);
ans2=max(ans2,f2[i][i+n-]);
}
printf("%d\n%d",ans1,ans2);
}

放上环状代码

对于括号匹配这一类。

给一个括号组成的字符串,问最多能匹配多少个括号

我们可以把[i,j]区间的字符当成由[i+1,j]在前面加个字符或[i,j-1]在后面加一个字符得来的

这里我们只考虑[i,j]由[i+1,j]在前面加一个字符的情况 
如果a[i+1]到a[j]没有和a[i]匹配的,那么dp[i][j] = dp[i+1][j] 
如果a[k]和a[i]匹配(i < k <= j),那么dp[i][j] = max(dp[i][j], dp[i+1][k-1] + dp[k+1][j] + 2); 
比如:[xxxxx]yyyyy通过括号分成两个子串

第二种模型就是根据匹配信息把区间划分成[i+1,k-1]和[k+1,j]

while (gets(a+))
{
if(a[] == 'e') break;
memset(dp, , sizeof(dp));
int n = strlen(a+);
for (int len = ; len <= n; len++)
{
for(int i = , j = len; j <= n; i++, j++)
{
dp[i][j] = dp[i+][j];
for (int k = i; k <= j; k++)
if((a[i]=='('&&a[k]==')') || (a[i]=='['&&a[k]==']'))
dp[i][j] = max(dp[i][j], dp[i+][k-] + dp[k+][j] + );
}
}
printf("%d\n",dp[][n]);
}

代码还可以这样写

还有一类只需要枚举左右边界,比较简单,就不展开讲了。

区间DP入门的更多相关文章

  1. POJ 2955 Brackets (区间dp入门)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  2. hdu 4570 Multi-bit Trie 区间DP入门

    Multi-bit Trie 题意:将长度为n(n <= 64)的序列分成若干段,每段的数字个数不超过20,且每段的内存定义为段首的值乘以2^(段的长度):问这段序列总的内存最小为多少? 思路: ...

  3. POJ2955--Brackets 区间DP入门 括号匹配

    题意很简单,就是求给出串中最大的括号匹配数目.基础题,格式基本为简单区间dp模板. #include<iostream> #include<string.h> using na ...

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

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

  5. 区间DP入门题目合集

      区间DP主要思想是先在小区间取得最优解,然后小区间合并时更新大区间的最优解.       基本代码: //mst(dp,0) 初始化DP数组 ;i<=n;i++) { dp[i][i]=初始 ...

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

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

  7. poj 2955 区间dp入门题

    第一道自己做出来的区间dp题,兴奋ing,虽然说这题并不难. 从后向前考虑: 状态转移方程:dp[i][j]=dp[i+1][j](i<=j<len); dp[i][j]=Max(dp[i ...

  8. LightOJ 1422:Halloween Costumes(区间DP入门)

    http://lightoj.com/volume_showproblem.php?problem=1422 题意:去参加派对,有n场派对,每场派对要穿第wi种衣服,可以选择外面套一件,也可以选择脱掉 ...

  9. NYOJ 石子合并(一) 区间dp入门级别

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

随机推荐

  1. 详解Redis Cluster集群

    Redis Cluster是Redis的分布式解决方案,在Redis 3.0版本正式推出的,有效解决了Redis分布式方面的需求.当遇到单机内存.并发.流量等瓶颈时,可以采用Cluster架构达到负载 ...

  2. E20180404-hm

    reject vt. 拒绝; 排斥; 抛弃,扔掉; 吐出或呕吐; conditioner  n. 调节器,调节装置 fabric n. 织物; 布; 构造; (建筑物的) 结构(如墙.地面.屋顶):质 ...

  3. poj1308【并查集】

    = =.如果输入的两个数相等.就不是一颗树啊,不能自己指向自己. 水.(瞎开的数组). //#include <bits/stdc++.h> #include<iostream> ...

  4. 骨骼蒙皮动画(SkinnedMesh)的原理解析(一)

    http://blog.csdn.net/jimoshuicao/article/details/9253999 一)3D模型动画基本原理和分类 3D模型动画的基本原理是让模型中各顶点的位置随时间变化 ...

  5. git 命令参考手册

    你的本地仓库由 git 维护的三棵“树”组成.第一个是你的 工作目录,它持有实际文件:第二个是 缓存区(Index),它像个缓存区域,临时保存你的改动:最后是 HEAD,指向你最近一次提交后的结果. ...

  6. CDH版本大数据集群下搭建的Hue详细启动步骤(图文详解)

    关于安装请见 CDH版本大数据集群下搭建Hue(hadoop-2.6.0-cdh5.5.4.gz + hue-3.9.0-cdh5.5.4.tar.gz)(博主推荐) Hue的启动 也就是说,你Hue ...

  7. The Django Book学习笔记 04 模板

    如果使用这种方法制作文章肯定不是一个好方法,尽管它便于你理解是怎么工作的. def current_datetime(request): now = datetime.datetime.now() h ...

  8. ASP.NET Core Action 读取流

    以前mvc5 action可以直接使用 var stream = HttpContext.Current.Request.InputStream; 读取流,在Core中有所不同,可以使用以下方式读取 ...

  9. gbk编码文件传输json实例

    cline.php <?php $str='此地无银三百两'; $str = iconv('gbk', 'utf-8', $str); //Json只支持utf-8编码,如果不进行转码的话,服务 ...

  10. maven编译报错 -source 1.5 中不支持 lambda(或diamond) 表达式,编码 UTF-8 的不可映射字符

    在用maven编译项目是由于项目中用了jdk 1.8, 编译是报错  -source 1.5 中不支持 lambda 表达式. 错误原因: Maven Compiler 插件默认会加 -source ...