括号匹配问题(区间dp)
简单的检查括号是否配对正确使用的是栈模拟,这个不必再说,现在将这个问题改变一下:如果给出一个括号序列,问需要把他补全成合法最少需要多少步?
这是一个区间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)的更多相关文章
- POJ 2955 括号匹配,区间DP
		
题意:给你一些括号,问匹配规则成立的括号的个数. 思路:这题lrj的黑书上有,不过他求的是添加最少的括号数,是的这些括号的匹配全部成立. 我想了下,其实这两个问题是一样的,我们可以先求出括号要匹配的最 ...
 - poj2955:括号匹配,区间dp
		
题目大意: 给一个由,(,),[,]组成的字符串,其中(),[]可以匹配,求最大匹配数 题解:区间dp: dp[i][j]表示区间 [i,j]中的最大匹配数 初始状态 dp[i][i+1]=(i,i+ ...
 - POJ 2955 Brackets --最大括号匹配,区间DP经典题
		
题意:给一段左右小.中括号串,求出这一串中最多有多少匹配的括号. 解法:此问题具有最优子结构,dp[i][j]表示i~j中最多匹配的括号,显然如果i,j是匹配的,那么dp[i][j] = dp[i+1 ...
 - POJ - 2955 Brackets括号匹配(区间dp)
		
Brackets We give the following inductive definition of a “regular brackets” sequence: the empty sequ ...
 - 括号序列(区间dp)
		
括号序列(区间dp) 输入一个长度不超过100的,由"(",")","[",")"组成的序列,请添加尽量少的括号,得到一 ...
 - 九度OJ 1153:括号匹配问题 (DP)
		
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5193 解决:2248 题目描述: 在某个字符串(长度不超过100)中有左括号.右括号和大小写字母:规定(与常见的算数式子一样)任何一个左括 ...
 - NYOJ15-括号匹配(二)-区间DP
		
pid=15">http://acm.nyist.net/JudgeOnline/problem.php? pid=15 dp[i][j]表示从i到j至少须要加入多少个括号才干满足匹配 ...
 - 区间DP 基本题集
		
51 Nod 1021 石子归并 模板题,敲就完事了,注意一下这种状态转移方程有个四边形的优化(时间) #include <cstdio> #include <iostream> ...
 - 集训第五周动态规划 J题  括号匹配
		
Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...
 - poj2955括号匹配 区间DP
		
Brackets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5424 Accepted: 2909 Descript ...
 
随机推荐
- unity3d绘画手册-------地形各个参数解释
			
关于Unity3D是什么.我就不多做解释了.由于工作原因,该系列原创教程不定期更新.每月必然有更新.谢谢各位. Unity地形:: 新建地形: <ignore_js_op> 如图在菜单中新 ...
 - erlang在NotePad++下的高亮
			
转自:http://www.roberthorvick.com/2009/07/08/syntax-highlighing-for-erlang-in-notepad/ Syntax Highligh ...
 - jquery widgets 弹框
			
<div id='dialog' style="display:none;"> <div style="text-align:center;" ...
 - Java精选笔记_面向对象(慨念、类和对象)
			
面向对象概念 在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象. 相对于面向过程而言.是一种思想,强调的是功能的对象. 面向对象的本质:以类的方式组织代码, ...
 - Android 中如何从一个App启动另外一个App(如启动支付界面、启动地图界面、应用商场下载App等场景)
			
假定两个App,分别是A和B,当A运行某个功能需要启动B,一种是启动B应用,一种直接进入B的某个Activity.搜了很多资料,没有一个完整的.下面就A--Android5.1.1.B--Androi ...
 - 如何才能知道外线是FSK还是DTMF制式?
			
在直线上接上来电显示话机,然后用手机或其他电话拨接电话的外线号码. 1.如果是先振铃后来显,就是FSK制式. 2.如果先送来显,再振铃或来显和振铃同时响应,就是DTMF制式 交换机默认配置是FSK制式 ...
 - linux解压和压缩
			
1.压缩命令: 命令格式:tar -zcvf 压缩文件名.tar.gz 被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2.解压缩命令: 命令格式:tar -z ...
 - Linux 虚拟终端:screen
			
screen 是一个虚拟终端,我们可以把执行时间很长的命令放在虚拟终端中执行,即使终端断开,这个虚拟终端也会在后台执行 [root@localhost ~]$ yum install -y scree ...
 - SaltStack 如何自定义 grains 信息
			
首先在 minion 上编辑 grains 配置文件,然后添加自定义的 grains: [root@localhost ~]$ cat /etc/salt/grains # 这个文件默认是没有的 ro ...
 - 编写一个读写倾斜测量数据.s3c文件格式的OSG插件osgdb_s3c
			
VS新建一个空的DLL工程 ReaderWriterS3C.cpp源文件 #include <osg/Notify> #include <osgDB/FileNameUtils> ...