0w1

UVA 1626 Brackets sequence ( DP 括弧匹配 )

UVa Online Judge
題目大意:給定一個括弧序列,可任意增加、插入括弧,求最少增加的情況下的合法括弧序列。
可以考慮遞迴,一個序列大致有三種情況可以處理,一種是它的外部是合法的,可以試著直接將外部刪去,第二種是在某個切割點分開的情況做分治,這就枚舉所有分割點,最後一種是序列長度只有 1,那麼直接增加另一邊使它合法就行了。這麼一來,只要令 dp( i, j )為序列 [ i, j )需要最少增加的括弧數,就能做到 O( N ^ 3 )。至於打印解序列的部分,一步一步根據狀態轉移式回朔到邊界,遞迴打印就可以了。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100 + 5;
const int INF = 1e9;

int n;
string s;
int memo[MAXN][MAXN];

int dp(int ql, int qr){ // [ ql, qr )
    if( ql == qr ) return 0;
    if( ql + 1 == qr ) return 1;
    if( memo[ql][qr] < INF ) return memo[ql][qr];
    for(int i = ql + 1; i < qr; ++i)
        memo[ql][qr] = min( memo[ql][qr], dp( ql, i ) + dp( i, qr ) );
    if( s[ql] == '(' && s[qr-1] == ')' ) 
        memo[ql][qr] = min( memo[ql][qr], dp( ql+1, qr-1 ) );
    if( s[ql] == '[' && s[qr-1] == ']' ) 
        memo[ql][qr] = min( memo[ql][qr], dp( ql+1, qr-1 ) );
    return memo[ql][qr];
}

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

void print(int ql, int qr){
    if( qr - ql <= 0 ) return;
    if( qr - ql == 1 ){
        if( s[ql] == '(' || s[ql] == ')' ) cout << "()";
        else cout << "[]";
        return;
    }
    if( match( s[ql], s[qr-1] ) && dp( ql, qr ) == dp( ql + 1, qr - 1 ) ){
        cout << s[ql]; print( ql+1, qr-1 ); cout << s[qr-1];
        return;
    }
    for(int i = ql + 1; i < qr; ++i)
        if( dp( ql, qr ) == dp( ql, i ) + dp( i, qr ) ){
            print( ql, i ); print( i, qr );
            return;
        }
}

int main(){
    ios::sync_with_stdio(false);
    int T; cin >> T; getline( cin, s );
    bool first = true;
    while( T-- ){
        if( first ) first = false;
        else cout << endl;
        getline( cin, s ); // eat blank line
        getline( cin, s );
        n = s.size();
        for(int i = 0; i <= n; ++i)
            for(int j = 0; j <= n; ++j)
                memo[i][j] = INF;
        dp( 0, n );
        print( 0, n );
        cout << endl;
    }
    return 0;
}