UVa 1626

来源:互联网 发布:form表单怎么提交数据 编辑:程序博客网 时间:2024/04/28 07:08

题目大意是给定一个括号序列,添加最少的括号使这个序列匹配并且打印出来

思路

区间DP

首先设计状态,d(i, j)表示当前序列的开头位置是i,结束位置是j的最短需要添加的括号的个数,对于当前的括号序列,如果最左面的括号

和最右面的括号匹配,则它的最小值应为d(i, j) = min{d(i, j), d(i + 1, j - 1)}, 同时取d(i, j) = min{d(i, j), min{d(i, k) + d(k + 1, j)}} k >= i & k < j

递推形式比记忆化搜索要快。打印每次递归寻找最优值打印即可。

#include <bits/stdc++.h>using namespace std;const int INF = 1000000000;const int maxn = 200 + 10;int d[maxn][maxn], vis[maxn][maxn];int n;char s[maxn];int dp(int i, int j){    if(i == j) return d[i][j] = 1;    else if(i > j) return d[i][j] = 0;    int & val = d[i][j];    if(vis[i][j]) return val;    vis[i][j] = 1;    int Min = n;    if((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']'))        Min = min(Min, dp(i + 1, j - 1));    for(int k = i; k < j; ++k){        Min = min(Min, dp(i, k) + dp(k + 1, j));    }    return val = Min;}void print(int i, int j){    if(i > j) return;    int val = d[i][j];    if(i == j){        if(s[i] == '(' || s[i] == ')') printf("()");        else printf("[]");        return;    }    if(((s[i] == '[' && s[j] == ']') || (s[i] == '(' && s[j] == ')'))       && val == d[i + 1][j - 1]){        printf("%c", s[i]);        print(i + 1, j - 1);        printf("%c", s[j]);        return;    }    for(int k = i; k < j; ++k){        if(d[i][k] + d[k + 1][j] == val){            print(i, k); print(k + 1, j);            break;        }    }}int main(){    int T; scanf("%d", &T);    getchar();    while(T --){        gets(s);        gets(s);        memset(vis, 0, sizeof(vis));        n = strlen(s);        int res = dp(0, n - 1);        print(0, n - 1);        puts("");        if(T) puts("");    }    return 0;}

0 0
原创粉丝点击