1. 程式人生 > 其它 >[Acwing藍橋杯DP] 1070. 括號配對

[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!!!