[Acwing藍橋杯DP] 1070. 括號配對
阿新 • • 發佈:2022-04-02
題目大意:給一個長度為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!!!