括号匹配(二)

时间限制:1000 ms  |  内存限制:65535 KB
难度:6
 
描述
   给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
 
输入
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出
对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
样例输入
4
[]
([])[]
((]
([)]
样例输出
0
0
3
2

对于这道题,我还是跟②2017=5.13-7.1中的合并石子一样,贴出两份不同的类型的题解以及解释。
思路其实差不多,是枚举过程有些差异,分给两种不同习惯的人。
DP[i][j]指i到j中合法括号配对数。比如对于字符串(),DP[1][2]=2。SP[]用于存储括号字符串,我是从下标1存储起的。N存储字符串的长度。
我们可以这样想,DP[i][j]合法的情况只有以下三种:
1.SP[i]=='('&&SP[j]==')'且DP[i+1][j-1]合法。
2.SP[i]=='['&&SP[j]==']'且DP[i+1][j-1]合法。3.能够切成两段合法的括号序列。 我们可以计算出合法的括号配对数,然后用字符串长度减去它,就是答案。这里合法的括号配对数指:比如对于字符串(),DP[1][2]=2,则合法括号配对数指2。
第一种题解:
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int T,DP[][],N;
char SP[];
int main()
{
scanf("%d",&T);
while (T--) {
N=;
scanf("%s",SP+);
while (SP[N+]) N++;
memset(DP,,sizeof(DP));
for(int i=N-; i>=; i--)
for(int j=i+; j<=N; j++) {
if ((SP[i]=='('&&SP[j]==')')||(SP[i]=='['&&SP[j]==']'))
DP[i][j]=DP[i+][j-]+;
for (int k=i; k<j; k++)
DP[i][j]=max(DP[i][j],DP[i][k]+DP[k+][j]);
}
printf("%d\n",N-DP[][N]);
}
return ;
}

code1

我仍然挑出部分代码讲解:

memset(DP,0,sizeof(DP));//因为有T组数据,所以对于每一组数据我们都需要初始化DP数组。
for(int i=N-1; i>=1; i--)
  for(int j=i+1; j<=N; j++) {
    if ((SP[i]=='('&&SP[j]==')')||(SP[i]=='['&&SP[j]==']'))//第1、2种合法情况的判断。
      DP[i][j]=DP[i+1][j-1]+2;//括号有两边,所以+2;
    for (int k=i; k<j; k++)
      DP[i][j]=max(DP[i][j],DP[i][k]+DP[k+1][j]);//对于第三种情况的判断。
  }
printf("%d\n",N-DP[1][N]);

肯定有人要问:为什么DP[i][j]=max(DP[i][j],DP[i][k]+DP[k+1][j]);就可以计算出如([])()这样的情况的答案呢?

是这样的,我们可以这么想:假如k枚举到了3,那么DP[1][3]就是2,DP[4][6]也是2,DP[1][6]答案就是4。

假如k枚举到了4,那么DP[1][4]答案就是4,DP[5][6]答案就是2,DP[1][6]的答案就是6,大于原来的答案且合法,于是更新。

这样就可以完美地从括号中间分割出来啦~因为如果()()是类似这样的合法括号序列,从中间分割出来的答案一定是最优的,所以就可以保证答案的正确性啦!

这种写法的原理是:当i相同时,j小的先算;当i不相同时,i大的先算。

比如:DP[i][k]比DP[i][j]先算,因为i=i,k比较小;DP[k+1][j]比DP[i][j]先算,因为k+1不等于i,k+1>i。

这样就可以保证循环先后的正确性,也就是保证我们计算这一步需要用的东西在计算这一步之前就计算好了。

第二种写法:
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int T,DP[][],N;
char SP[];
int main()
{
scanf("%d",&T);
while (T--) {
N=;
scanf("%s",SP+);
while (SP[N+]) N++;
memset(DP,,sizeof(DP));
for (int LEN=; LEN<=N; LEN++)
for (int i=,j=LEN; j<=N; i++,j++) {
if ((SP[i]=='(' && SP[j]==')')||(SP[i]=='['&&SP[j]==']'))
DP[i][j]=DP[i+][j-]+;
for (int k=i; k<j; k++)
DP[i][j]=max(DP[i][k]+DP[k+][j],DP[i][j]);
}
printf("%d\n",N-DP[][N]);
}
return ;
}

code2

这种写法其实本质上和第一种是一样的,只是枚举的方式略有不同,是通过枚举序列长度来保证DP循环的先后性的,所以放出来给熟悉这种写法的人看。


memset(DP,0,sizeof(DP));//初始化
for (int LEN=2; LEN<=N; LEN++) //枚举序列长度
  for (int i=1,j=LEN; j<=N; i++,j++) {
    if ((SP[i]=='(' && SP[j]==')')||(SP[i]=='['&&SP[j]==']'))//第1、2种合法情况的判断。
      DP[i][j]=DP[i+1][j-1]+2;//括号有两边,所以+2;
    for (int k=i; k<j; k++)
      DP[i][j]=max(DP[i][k]+DP[k+1][j],DP[i][j]);//对于第三种情况的判断。
  }
printf("%d\n",N-DP[1][N]);

对于第三种情况的判断上面讲的很清楚了。

有问题可以直接在评论里面提问,有需要转载的请得到我的允许,否则按侵权处理。


Elena loves NiroBC forever!

NYOJ15|括号匹配(二)|区间DP|Elena的更多相关文章

  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. NYOJ15-括号匹配(二)-区间DP

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

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

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

  6. NYOJ15括号匹配

    NYOJ15括号匹配 括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6   描述 给你一个字符串,里面只包含"(",")" ...

  7. 「kuangbin带你飞」专题二十二 区间DP

    layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...

  8. 括号序列(区间dp)

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

  9. 【栈思想、DP】NYOJ-15 括号匹配(二)

    括号匹配(二) 描述 给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能 ...

随机推荐

  1. RPC框架-hessian学习

    先说说hessian有什么优点和缺点 一.优点: 比 Java 原生的对象序列化/反序列化速度更快, 序列化出来以后的数据更小.序列化协议跟应用层协议无关, 可以将 Hessian 序列化以后的数据放 ...

  2. 编写SHELL脚本--编写简单脚本

    1.简单脚本文件hello.sh,内容如下 #!/bin/bash pwd ls -al 执行脚本:bash hello.sh  或者使用root命令:  ./hello.sh 2.接受用户参数 $0 ...

  3. Boinx FotoMagico for Mac(电子相册制作工具)破解版安装

    1.软件简介    FotoMagico 是 macOS 系统上一款非常好用的电子视频相册制作工具,FotoMagico 被誉为 Mac 上的「会声会影」,我们可以使用这款软件快速的制作出精美的音乐视 ...

  4. 11g新特性-自动sql调优(Automatic SQL Tuning)

    11g新特性-自动sql调优(Automatic SQL Tuning) 在Oracle 10g中,引进了自动sql调优特性.此外,ADDM也会监控捕获高负载的sql语句. 在Oracle 11g中, ...

  5. Lambert漫反射的BRDF

    Lambert漫反射brdf=Albedo/pi. 推导: 如图,设Lambert面元获得入射照度Ei,各方向均匀释放亮度,每个方向释放的亮度都是Lo. 又设此表面反射率为Albedo,根据反射率定义 ...

  6. java解析Excel(xls、xlsx两种格式)

    https://www.cnblogs.com/hhhshct/p/7255915.html ***************************************************** ...

  7. android开发(46) 使用 textview实现文字的阴影效果,浮雕效果

    前言 最近看到一些文字的阴影效果很有意思,尝试了下,形成本文.“平面效果“是我们平时常见的平面的样子.“阴影效果”会给人一种凸起的感觉.浮雕效果会给一种雕刻“凹陷”的感觉. 演示效果图 方法 使用 t ...

  8. 嵌入式开发之hi3519---i2c MDIO PHY uboot phy调试总结

    首先调试检查硬件,再调试软件 首先仔细阅读phy和主芯片datesheet ,尤其着重阅读mii寄存器,它是mac和phy交换信息的媒介. 硬件注意:关于phy的芯片需要注意的有几点:1.mdio接口 ...

  9. file_name[:-4]

    file_name: chair_0001.off file_name[:-4] : chair_0001

  10. Mac mysql 修改密码

    如果你知道密码: mysqladmin -u root -p password 新密码 MYSQL数据库密码忘记: 1. 在系统偏好 中,中止MYSQL服务.: 2. cd/usr/local/mys ...