POJ 1141:Brackets Sequence

题意:

定义合法串为(),[]以及他们的并列组合如()[],()(),或嵌套组合如([]),(())。 其实正常理解就好~

然后给你一个串,让你求出把它改对后的最短合法串。

类型:

DP动态规划

思路:

当我拿到一个字符i, 那么在一种最优结果中,它只有这么两种结果:要么和某个字符匹配,要么不匹配。

定义状态:

dp[i][j]为  i到j的子串中  所能做到的最大匹配数符号数。

最大匹配符号数说明:如(([))]] 如果这么匹配(([))]]   数量为2,  而这样匹配 (([))]] 数量为4。易知后者也是最大的,所以这个子串最大匹配符号数为4.

状态转移:

首先特判:若i所在字符与j所在字符能匹配(() 或 []) 那么尝试匹配这两个字符

ans = dp[i+1][j-1] + 2;

然后,不匹配ij两个字符,尝试把字符串分成两段(i,i+k) (i+k+1, j)(那么这里其实是假想让i字符与当中第i+k个字符匹配,当k=0时其实就是不匹配。k从0到j-i-1)

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
//18:09

char str[200];
int dp[120][120];
int flag[200][200];
int chooes[200];

int dfs(int i, int j)
{
    if (dp[i][j] != -1) return dp[i][j];
    if (j - i < 1) return dp[i][j] = 0;

    int &ans = dp[i][j];
    if (str[i] == '(' && str[j] == ')' || str[i] == '[' && str[j] == ']')
    {
        ans = dfs(i+1, j-1) + 2;
        flag[i][j] =  -99;
    }
    int k;
    for (k = 0; k < j-i; k++)
    {
        if (ans < dfs(i,i+k) + dfs(i+k+1, j)) {
            ans = dfs(i,i+k) + dfs(i+k+1, j);
            flag[i][j] = k;
        }
    }

    return ans;
}

int main()
{
    //while (scanf("%s", str+1) != EOF)
    scanf("%s", str+1);
    {
        memset(dp, -1, sizeof(dp));
        memset(chooes, 0, sizeof(chooes));

        int len = strlen(str+1);

        dfs(1, len);

        // Use stack to find which is choosen
        int i = 1; int j = len;
        int si[200], sj[200];
        int pi = 0, pj = 0;
        si[pi++] = 1;
        sj[pj++] = len;

        while (pj) {
            i = si[--pi];
            j = sj[--pj];
            if (flag[i][j] == -99) {  //Choosen
                chooes[i] = chooes[j] = 1;
                si[pi++] = i+1;
                sj[pj++] = j-1;
            } else if (j-i>=1) {
                si[pi++] = i;
                sj[pj++] = i+flag[i][j];

                si[pi++] = i+flag[i][j]+1;
                sj[pj++] = j;
            }
        }


        for (i = 1; i <= len; i++) {
            if (chooes[i]) putchar(str[i]); // Those who is choosen needn't to fix
            else {
                switch (str[i]) {
                    case '(':
                    case ')':  printf("()");break;
                    case '[':
                    case ']':  printf("[]");break;
                }
            }
        }
        puts("");
    }
    return 0;
}
POJ 1141:Brackets Sequence O(n2)
原文地址:https://www.cnblogs.com/shinecheng/p/3080198.html