zoukankan      html  css  js  c++  java
  • 括号匹配(POJ2955)题解

    原题地址:http://poj.org/problem?id=2955

    题目大意:给出一串括号,求其中的最大匹配数。

    我这么一说题目大意估计很多人就蒙了,其实我看到最开始的时候也是很蒙的。这里就来解释一下题意。

    这道题让求的是最大常规匹配数,什么是常规匹配呢?

    ()  []  ()[]  []()  [()]都是常规序列。

    翻译一下题目的英文:

    我们给出了“常规括号”序列的以下归纳定义:

    • 空序列是常规括号序列,
    • 如果s是常规括号序列,则(s)和[ s ]是常规括号序列,并且
    • 如果ab是常规括号序列,则ab是常规括号序列。
    • 没有其他序列是常规括号序列

    样例输入

    ((()))
    ()()()
    ([]])
    )[)(
    ([][][)
    end

    样例输出

    6
    6
    4
    0
    6

    现在开始说思路。
    很明显,这是一道区间DP,因为大的常规括号一定是包含小的常规括号的,满足我们区间DP的要求。
    区间DP常用枚举方式见
    https://www.cnblogs.com/lizitong/p/10014809.html
    首先是状态,非常简单,dp[i][j]表示从i到j的最大匹配数,我们要求的答案就是dp[1][n]
    我们开始枚举,假如我们枚举到的[i][j]中,第i个和第j个是匹配的括号,即()或者[ ]
    那么dp[i][j]=dp[i+1][j-1]+2;
    没错吧,我们只需要在原基础上+2就好了。
    如果[i] 和[j]不匹配呢?
    那我们可以把这个区间分为两段,以k为分界点。
    分成[i][k],[k+1][j]两段,然后把两段的值相加就好了。因为这两个括号不匹配,不代表其中的不匹配。人不能在一棵树上吊死。
    需要注意的是,即使是[i]和[j]两个括号匹配,仍需枚举k来判断是否可以将这个区间分成两段,因为这样得到的仍然可能不是最优解。
    例如:()()这个序列。
    显然答案应该为4,但是最左面和最右面匹配,而中间 ")("
    区间的答案为0,导致最后的结果为2。
    枚举k的时候需要注意枚举范围。
    上代码。
    提示:个人区间是从0存到的n-1。
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    using namespace std;
    char a[105];
    int dp[105][105];
    int main()
    {
          while(scanf("%s",a)!=EOF)
          {       
                if(a[0]=='e')
                {
                      return 0;
                }
                int n = strlen(a);
                memset(dp,0,sizeof(dp));
                for(int len = 2;len<=n;len++)
                {
                      for(int i = 0;i+len-1<=n-1;i++)
                      {
                            int j = i+len-1;
                            if((a[i]=='('&&a[j]==')')||(a[i]=='['&&a[j]==']'))
                            {
                                  dp[i][j] = max(dp[i][j],dp[i+1][j-1]+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",dp[0][n-1]);
          }
          return 0;
    }
    
    
    
     
  • 相关阅读:
    配置Gitlab pages和Gitlab CI
    程序员不应该错过的 6大导航
    Ice简介+Qt代码示例
    Android开发者的Anko使用指南(四)之Layouts
    三种方式绘制图片
    产品-(前后端)开发-测试的见解
    01_Docker概念简介、组件介绍、使用场景和命名空间
    Docker 创建 Confluence6.12.2 中文版
    读再多懂再多的鸡汤,不如每天敲码思考总结
    Postman Mock Server
  • 原文地址:https://www.cnblogs.com/lizitong/p/10020674.html
Copyright © 2011-2022 走看看