[Acwing蓝桥杯DP] 1070. 括号配对
题目大意:给一个长度为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!!!

浙公网安备 33010602011771号