• Bzoj P2461 [BeiJing2011]符环 题解


    每日一题 day65 打卡

    因为markdown实在是太麻烦了,所以等开学了再用吧。

    Analysis

    这道题很有意思,题目有些难懂,主要意思是输入的字符串中第 i 位规定了最后括号序列的第 i 位和第 len+i 位的括号是否相同。

    问最后组成了一个合法的括号序列,有多少种情况。

    很容易想到的一个做法就是每次枚举是‘( ’还是‘ )’。但是因为n最大为50,所以显然是不行的。(复杂度为2^50)

    又因为题目只问了情况数没有问具体的情况是什么,所以我们可以考虑用dp数组来表示状态再记忆化搜索,这样时间复杂度就可以保证。

    那么现在的问题是,如何在可以接受的空间复杂度内来表示状态?

    第一维显然是当前枚举到的字符串的位置。

    因为要为了最后能判断是否为合法的括号序列,所以按理来说要再记录四维:1~n左括号未匹配的个数,1~n右括号未匹配的个数,n+1~2n左括号未匹配的个数,n+1~2n右括号未匹配的个数。

    这样的话就空间炸了。

    那怎么办呢?

    我们可以发现,1~n右括号未匹配的个数是没必要记录的,因为如果出现1~n有未匹配的右括号,你无论如何也无法使其最后变为合法。

    所以我们可以删掉一维,这样最后的空间复杂度就是50^4,可以接受。

    到目前为止,大体思路已经成型了,一些细节我会在代码中为大家讲解。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 #define maxn 50+1
     7 #define rep(i,s,e) for(register int i=s;i<=e;++i)
     8 #define dwn(i,s,e) for(register int i=s;i>=e;--i)
     9 using namespace std;
    10 inline int read()
    11 {
    12     int x=0,f=1;
    13     char c=getchar();
    14     while(c<'0'||c>'9') {if(c=='-') x=-x; c=getchar();}
    15     while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
    16     return f*x;
    17 }
    18 inline void write(int x)
    19 {
    20     if(x<0){putchar('-');x=-x;}
    21     if(x>9)write(x/10);
    22     putchar(x%10+'0');
    23 }
    24 int t,n,len;
    25 char a[maxn];
    26 int dp[maxn][maxn][maxn][maxn];
    27 int dfs(int now,int x,int y,int z)
    28 {
    29     if(now==len+1)
    30         return z==0&&x==y;//判断是否合法 
    31     int &val=dp[now][x][y][z];
    32     if(val!=-1) return val;
    33     val=0;
    34     if(a[now]=='S')
    35     {
    36         val+=dfs(now+1,x+1,y,z+1);//在1~n和n+1~2n中分别放上一个‘(’ 
    37         if(z!=0&&x!=0) val+=dfs(now+1,x-1,y,z-1);//在n+1~2n中有 没有匹配的左括号的情况下,在1~n和n+1~2n中分别放上一个‘)’ 
    38         else if(x!=0) val+=dfs(now+1,x-1,y+1,z);//在n+1~2n中没有 没有匹配的左括号的情况下,在1~n和n+1~2n中分别放上一个‘)’
    39     }
    40     else if(a[now]='D')//与上面同理 
    41     {
    42         if(x!=0) val+=dfs(now+1,x-1,y,z+1);
    43         if(z!=0) val+=dfs(now+1,x+1,y,z-1);
    44         else val+=dfs(now+1,x+1,y+1,z);
    45     }
    46     return val;
    47 }
    48 signed main()
    49 {
    50     t=read();
    51     dwn(i,t,1)
    52     {
    53         memset(dp,-1,sizeof(dp));
    54         cin>>a+1;
    55         len=strlen(a+1);
    56         write(dfs(1,0,0,0));
    57         putchar('
    ');
    58     }
    59     return 0;
    60 }

    如有失误请各位大佬斧正(反正我不认识斧正是什么意思)

  • 相关阅读:
    第五周课堂测试补充
    20162327WJH2016-2017-2《程序设计与数据结构》课程总结
    20162327WJH实验五——数据结构综合应用
    20162327WJH实验四——图的实现与应用
    20162327 《程序设计与数据结构》第十一周学习总结
    20162327WJH第三次实验——查找与排序2
    20162327 《程序设计与数据结构》第九周学习总结
    20162327WJH第二次实验——树
    20162327 《程序设计与数据结构》第七周学习总结
    20162327WJH使用队列:模拟票务站台代码分析
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/12344395.html
Copyright © 2020-2023  润新知