zoukankan      html  css  js  c++  java
  • 括号序列 解题报告

    括号序列

    题目背景

    你不努力,未来别人腿咚的墙还是你砌的!

    题目描述

    课堂上,Felix刚刚学习了关于括号序列的知识。括号序列是一个只由左括号"("和右括号")"构成的序列:进一步的,一个合法的括号序列是指左括号和右括号能够一一匹配的序列。

    如果用规范的语言说明,一个合法的括号序列可以有以下三种形式:

    1 s=""(空串),s是一个合法的括号序列

    2 s=XY,其中X,Y均为合法的括号序列,则S也是一个合法的括号序列;

    3 s=(X),其中X为合法的括号序列,则S也是一个合法的括号序列。

    这时老师在黑板上写出了一个括号序列:"()))()"

    Felix一眼就看出这个序列并不是合法的括号序列。

    这时老师提出了一个这样的问题:能够在序列中找出连续的一段,把这一段里面的左括号变成右括号,右括号变成左括号,变换之后整个序列可以变成合法的呢?

    Felix想到,可以把[3..5]进行调换,这样序列就会变为()(()),是一个合法的序列。很明显,不止有一种方法可以使整个序列合法。

    这时,老师又在黑板上写出了一个长度为N的括号序列。Felix想,能否对这个序列进行至多一次变换,使他变合法呢?

    输入输出格式

    输入格式:

    第一行一个整数T,代表数据的组数;接下来T行,每一行一组数据。

    每组数据一行,代表给出的括号序列。

    输出格式:

    输出共T行,对于每组数据,输出“possible”(可以变换)或者“impossible”(不可变换)。(不含引号)

    说明

    对于50%的数据,T<=5,N<=20;

    对于100%的数据,T<=10,N<=5000。


    一开始想把已有的匹配括号全部缩掉直接贪心,搞了一会儿发现是错的。

    无奈,打了个暴力,枚举翻转区间并检查是否合法,居然还错了。。

    缺乏想到正解的原因是,我只知道拿栈来判断括号匹配,殊不知有实用性更好的方法。

    如果把括号抽象为一个数列,左括号为1,右括号为-1。

    对S的某个前缀p,如果数列的前缀和(f[p])的值大于0,则说明左括号数量不比右括号少。

    对于这个前缀p,如果每个(f)数组值大于等于0且(f[p]=0),则这个前缀p是匹配的。

    由此引入这个题的正解dp

    (dp[i][j][k])表示前缀(i)前缀和为(j)时处于(k)状态(0为翻转区间左边,1为翻转区间,2为翻转区间右边),进行可达性统计

    初始:(dp[0][0][0]=1)
    目标:(dp[n][0][0/1/2])

    可以滚动一下优化空间,另外这个题居然有点卡常。。


    #include <cstdio>
    #include <cstring>
    int max(int x,int y){return x>y?x:y;}
    const int N=5010;
    int f[N],t,dp[2][N][3];
    char c[N];
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",c);
            memset(f,0,sizeof(f));
            memset(dp,0,sizeof(dp));
            int n=strlen(c);
            for(int i=0;i<n;i++)
                f[i+1]=c[i]=='('?1:-1;
            dp[0][0][0]=1;
            for(int i=1;i<=n;i++)
            {
                for(int j=0;j<=i;j++)
                    for(int k=0;k<=2;k++)
                        dp[i&1][j][k]=0;
                int t=f[i];
                for(int j=0;j<=i;j++)
                {
                    if(j>=t)
                    {
                        dp[i&1][j][0]=dp[i-1&1][j-t][0];
                        dp[i&1][j][2]=max(dp[i-1&1][j-t][1],dp[i-1&1][j-t][2]);
                    }
                }
                t=-t;
                for(int j=0;j<=i;j++)
                    if(j>=t)
                        dp[i&1][j][1]=max(dp[i-1&1][j-t][0],dp[i-1&1][j-t][1]);
            }
            if(dp[n&1][0][0]||dp[n&1][0][1]||dp[n&1][0][2])
                printf("possible
    ");
            else
                printf("impossible
    ");
        }
        return 0;
    }
    
    

    2018.6.21

  • 相关阅读:
    20145220&20145209&20145309信息安全系统设计基础实验报告(1)
    20145309信息安全系统设计基础第8周学习总结下
    20145309信息安全系统设计基础第8周学习总结上
    20145309信息安全系统设计基础第7周学习总结下
    20145309信息安全系统设计基础第7周学习总结上
    20145309信息安全系统设计基础第6周学习总结下
    第六周学习总结1
    20145309 《信息安全系统设计基础》第5周学习总结
    20145309信息安全系统设计基础第3周学习总结
    20145306 信息安全系统设计基础 第五周博客总结
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9210530.html
Copyright © 2011-2022 走看看