CF162J Brackets 题解

CF162J Brackets

看到两位用栈匹配括号的大佬,这里提供另一个思路。

对于括号的问题,我们考虑区间DP

设状态 \(dp[i][j]\) 表示使区间 \([i,j]\) 内的括号匹配需要添加的括号数量,则转移方程如下:

\(1\) :区间两边括号匹配时,因为最外层不需要匹配,需要添加的括号数量取决于最外层括号内的需要添加的括号数量,也就是 \(dp[i+1][j-1]\) 的值。

\[dp[i][j]=\min\{dp[i][j],dp[i+1][j-1]\} \]

\(2\) :枚举分割点 \(k\) ,把原区间分 \([i,k]\)\([k+1,j]\) 两个区间,然后求和,把使两个子区间需要添加的括号数量合起来,就是总区间需要添加的括号数量。

\[dp[i][j]=\min\{dp[i][j],dp[i][k]+dp[k+1][j])\} \]

最后,如果使整个区间的括号匹配不需要任何括号,也就是说 \(dp[0][n-1]=0\) ,那么说明这个序列本来就是匹配的,输出 YES ,否则输出 NO

虽然复杂度是 \(O(n^3)\) ,但是由于序列长度最长只有 \(100\) ,还是可以做的。

C++版本代码如下:

#include <bits/stdc++.h>
using namespace std;
int f[600][600];
char s[600];
int main()
{
    scanf("%s",s);
    int n=strlen(s);
    for(int i=0;i<n;i++)f[i][i]=1;
    for(int l=2;l<=n;l++)
        for(int i=0;i+l-1<n;i++)
            {
                int j=i+l-1;
                f[i][j]=l;
                if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))f[i][j]=min(f[i][j],f[i+1][j-1]);
                for(int k=i;k<j;k++)
                    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); 
            }
    if(!f[0][n-1])printf("YES"); 
    else printf("NO");
    return 0;
}
posted @ 2025-02-12 08:26  w9095  阅读(19)  评论(0)    收藏  举报