POJ 1141 Brackets Sequence(区间DP + 打印路径)

题意:

寻找一种正确的括号匹配方案,并且打印出来。

思路:

1. 转移方程为:dp[i][j] = min(dp[i][k] + dp[k+1][j]); 如果 s[i] == s[j] 则还有 dp[i][j] = min(dp[i][j], dp[i+1][j-1]);

2. 因为涉及到打印路径,所以还要单独开辟一个数组出来,记录每次选择的结果。这也差不多是打印路径一类题定势的解题步骤;

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 110;
const int INFS = 0x3fffffff;
char s[MAXN];
int dp[MAXN][MAXN], choose[MAXN][MAXN];

void printstring(int i, int j) {
    if (i > j)
        return;

    if (i == j) {
        if (s[i] == '(' || s[i] == ')')
            printf("()");
        else
            printf("[]");
    } else if (choose[i][j] == -1) {
        printf("%c", s[i]);
        printstring(i + 1, j - 1);
        printf("%c", s[j]);
    } else {
        printstring(i, choose[i][j]);
        printstring(choose[i][j] + 1, j);
    }
}

int main() {
    while (gets(s)) {
        int len = strlen(s);
        for (int i = 0; i < len; i++)
            dp[i][i] = 1, dp[i+1][i] = 0;

        for (int p = 1; p < len; p++) {
            for (int i = 0, j = i + p; j < len; i++, j++) {
                dp[i][j] = INFS;
                choose[i][j] = -1;

                if ((s[i] == '(' && s[j] == ')') ||
                    (s[i] == '[' && s[j] == ']'))
                    dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
                
                for (int k = i; k < j; k++) {
                    if (dp[i][j] > dp[i][k] + dp[k+1][j]) {
                        choose[i][j] = k;
                        dp[i][j] = dp[i][k] + dp[k+1][j];
                    }
                }
            }
        }
        printstring(0, len - 1);
        printf("\n");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kedebug/p/2994155.html