简单的检查括号是否配对正确使用的是栈模拟,这个不必再说,现在将这个问题改变一下:如果给出一个括号序列,问需要把他补全成合法最少需要多少步?

这是一个区间dp问题,我们可以利用区间dp来解决,直接看代码吧!

 /* ***********************************************
Author :xiaowuga
Created Time :2017年10月03日 星期二 14时20分04秒
File Name :Desktop/text.cpp
************************************************ */
#include <bits/stdc++.h>
#define mem(s,ch) memset(s,ch,sizeof(s))
typedef long long LL;
#define inf 0x3f3f3f3f
const long long N=;
const long long mod=1e9+;
#define endl '\n'
using namespace std;
bool check(char a,char b){
if((a=='('&&b==')')||(a=='['&&b==']')) return true;
else return false;
}
int dp[][];
string q;
int main(){
ios::sync_with_stdio(false);cin.tie();
int n;
cin>>n;
while(n--){
cin>>q;
int len=q.size();
memset(dp,,sizeof(dp));
for(int i=;i<len;i++) dp[i][i]=;
for(int i=len-;i>=;i--){
for(int j=i+;j<len;j++){
dp[i][j]=inf;
if(check(q[i],q[j])) dp[i][j]=dp[i+][j-];
for(int k=i;k<j;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+][j]);
}
}
}
cout<<dp[][len-]<<endl;
}
return ;
}

虽然也有记忆化搜索的做法,但是刷表的方法似乎代码量更短,区间dp的刷表有一个特点i和j总是反过来,这是为什么呢?由于区间dp中大区间的答案依赖于小区间,所以我们在更新大区间答案的时候一定要保证向他发生状态转移的小区间都已经得出了答案。所以:

for(int i=len-2;i>=0;i--){

  for(int j=i;j<len;j++){

  }

}

自己枚举一下更新区间的顺序就会发现,当我们需要更新区间dp[i][j]的答案的时候dp[i][k-1]和dp[k+1][j]都已经更新了。

现在来解释一下:两种转移方式

  1.如果q[i]和q[j]是可以匹配的,dp[i][j]=dp[i-1][j-1](显然不解释了)

  2.对于一个区间,我们考虑把他分解成两个子区间,那么如果得到最优的子区间分配呢?答案是枚举,枚举所有的分配方式即

<[i,i],[i+1][j]>,<[i,i+1],[i+2,j]>,<[i,i+2],[i+3,j]>,<[i,i+3],[i+4,j]>,…………<[i,j-1],[j,j]>,找到所有分配方式最小值。

对于每一个区间我们找以上两种转移方式的最小值。

如果要打印打印方案(代码):

 void print(int l,int r){
if(l>r) return;
if(l==r){
if(q[l]=='('||q[l]==')') cout<<"()";
else if(q[l]=='['||q[l]==']') cout<<"[]";
return ;
}
if(check(q[l],q[r])&&dp[l][r]==dp[l+][r-]){
cout<<q[l];
print(l+,r-);
cout<<q[r];
return ;
}
for(int k=l;k<r;k++){
if(dp[l][r]==dp[l][k]+dp[k+][r]){
print(l,k);
print(k+,r);
return ;
}
}
}

这个这里相当于一个逆过程,如果你看了记忆化搜索代码应该就会很好理解这个代码了

记忆化搜索:

 int dp(int x,int y){
int &ans=d[x][y];
if(x>y) return ;
if(ans>||x==y) return ans;
ans=n;
if(match(str[x],str[y])) ans=min(ans,dp(x+,y-));
for(int i=x;i<y;i++){
ans=min(ans,dp(x,i)+dp(i+,y));
}
return ans;
}

练习题:

http://acm.nyist.net/JudgeOnline/problem.php?pid=15

https://vjudge.net/problem/UVA-1626

括号匹配问题(区间dp)的更多相关文章

  1. POJ 2955 括号匹配,区间DP

    题意:给你一些括号,问匹配规则成立的括号的个数. 思路:这题lrj的黑书上有,不过他求的是添加最少的括号数,是的这些括号的匹配全部成立. 我想了下,其实这两个问题是一样的,我们可以先求出括号要匹配的最 ...

  2. poj2955:括号匹配,区间dp

    题目大意: 给一个由,(,),[,]组成的字符串,其中(),[]可以匹配,求最大匹配数 题解:区间dp: dp[i][j]表示区间 [i,j]中的最大匹配数 初始状态 dp[i][i+1]=(i,i+ ...

  3. POJ 2955 Brackets --最大括号匹配,区间DP经典题

    题意:给一段左右小.中括号串,求出这一串中最多有多少匹配的括号. 解法:此问题具有最优子结构,dp[i][j]表示i~j中最多匹配的括号,显然如果i,j是匹配的,那么dp[i][j] = dp[i+1 ...

  4. POJ - 2955 Brackets括号匹配(区间dp)

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

  5. 括号序列(区间dp)

    括号序列(区间dp) 输入一个长度不超过100的,由"(",")","[",")"组成的序列,请添加尽量少的括号,得到一 ...

  6. 九度OJ 1153:括号匹配问题 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5193 解决:2248 题目描述: 在某个字符串(长度不超过100)中有左括号.右括号和大小写字母:规定(与常见的算数式子一样)任何一个左括 ...

  7. NYOJ15-括号匹配(二)-区间DP

    pid=15">http://acm.nyist.net/JudgeOnline/problem.php? pid=15 dp[i][j]表示从i到j至少须要加入多少个括号才干满足匹配 ...

  8. 区间DP 基本题集

    51 Nod 1021 石子归并 模板题,敲就完事了,注意一下这种状态转移方程有个四边形的优化(时间) #include <cstdio> #include <iostream> ...

  9. 集训第五周动态规划 J题 括号匹配

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

  10. poj2955括号匹配 区间DP

    Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5424   Accepted: 2909 Descript ...

随机推荐

  1. 转载:MySQL数据库INSERT、UPDATE、DELETE以及REPLACE语句的用法详解

    转自:http://www.jb51.net/article/39199.htm 本篇文章是对MySQL数据库INSERT.UPDATE.DELETE以及REPLACE语句的用法进行了详细的分析介绍, ...

  2. 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)

    转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...

  3. 页面的checkbox框的全选与反选

    if (typeof jQuery == 'undefined') {     alert("请先导入jQuery");} else {    jQuery.extend({    ...

  4. Python学习笔记(三)——迭代

    知识点 迭代 迭代 什么是迭代呢?和递归又有什么区别呢? 根据维基百科和网上的资料: 迭代:迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果.每一次对过程的重复被称为一次“迭代”, ...

  5. win7笔记本电脑怎么做wifi热点

    win7设置wifi热点后非常方便,可以给其他笔记本和手机之类支持无线上网的移动设备使用,接下来请看超简单的详细设置方法. 方法/步骤 1 第一步先打开“控制面板” 2 点击“网络和Internet” ...

  6. mysqlbinlog工具的作用是什么呢,如何将binary log转换为文本格式?

    需求描述: 今天在看mysqlbinlog这个工具,就在想这个工具到底是干嘛的呢,在mysql数据库中, binary log中记录了数据库内容的变化或者说修改,这些修改是以二进制的方式存储到 bin ...

  7. 制作ramdisk-u.img根文件系统

    具体步骤如下:1.解压内核源码树解压linux-2.6.29-mini2440-20090708.tgz到自己的工作目录,会生成一个友善之臂修改过的并且有几个mini2440默认配置文件的内核源码目录 ...

  8. 怎样设置table中td的高度为1px

    在制作edm时会遇到须要设置td的高度为1px,假设td标签中有 时不管你怎么设置td的高度都没用,最小高度都是18px. 这时须要把表格中的 去掉.例: 原来是这种: <tr> < ...

  9. 使用 C# 开发智能手机软件:推箱子(二)

    在上篇文章"使用 C# 开发智能手机软件:推箱子(一)"中.我对推箱子程序作了整体介绍.这次,我先介绍 Common/Fcl.cs 源程序文件.  1 using System; ...

  10. js 对象引用传值

    1)当变量是一个对象(例如:{}或[]),使用 a = b = {} 这种形式传值的话,会变成会用传值,修改 a 时 b 会相应变化,修改 b 时 a 也一样会相应变化 var a = b = {}; ...