[Acwing蓝桥杯DP] 1070. 括号配对

题目链接:1070. 括号配对 - AcWing题库

题目大意:给一个长度为n的字符串 ,至少添加多少字符能够满足 [ ( ) ] , [ ] ( )这种形式 。

数据范围: 1<=n<=110

分析:

这个题和 1222. 密码脱落 - AcWing题库 很像

不过相比密码脱落的回文串,加了一个条件 AABB型 也算。

整体思路差不多,就是一个区间的DP

直接来闫氏DP分析法:

区间:f [ i ][ j ] 表示:从 i 到 j 的字符串 至少加入几个字符 满足要求。

属性:最小值

区间划分  :

 

前四种和密码脱落的题一样

(1)l 和 r 都不选

(2)l 和 r 都选

(3)l选,r不选

(4)l不选,r选

(5)再另外判断 区间内的最小值 [ l , k ], [ k+1 , r] // l <= k < r

(判断子串是不是满足条件的,取最小值 , 因为区间长度是从小到大枚举的,所以这子区间里的 f 情况都已经计算过了所以可以放心枚举子区间)

初始化:长度为1的字符串 初始化为 1  f [ i ][ j ] = 1( i = j ) , 其他的字符串初始化为正无穷 ,因为是求最小值

这里的时间复杂度是O(n^3);

那么代码如下:

#include <bits/stdc++.h>

using namespace std;

const int N=110,INF=0x3f3f3f3f;

char s[N];
int n;
int f[N][N];

bool match(char l,char r)
{
    if(l=='('&&r==')')return true;
    if(l=='['&&r==']')return true;
    return false;
}

int main()
{
    scanf("%s",s);
    n=strlen(s);
    
    for(int len=1;len<=n;len++)
    {
        for(int i=0;i+len-1<n;i++)
        {
            int j=i+len-1;
            if(i==j)f[i][j]=1;
            else
            {
                f[i][j]=INF;
                if(match(s[i],s[j]))f[i][j]=f[i+1][j-1];
                f[i][j]=min(f[i][j],min(f[i+1][j],f[i][j-1])+1);
                for(int k=i;k<j;k++)
                {
                    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
                }
            }
        }
    }
    cout<<f[0][n-1]<<endl;
    
    return 0;
}

 

END!!! 

 

posted @ 2022-04-02 16:34  秦末  阅读(72)  评论(0)    收藏  举报
1 博文导航目录