POJ-1141-Brackets Sequence

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dreams___/article/details/79971862

img

题目链接:

Go!

题目大意:

​ 给你一个长度不超过 100 且只包含 (,),[,] 四种字符的字符串 s,添加 最少 的字符使其变成一个合法的字符串,输出这个合法的字符串

合法字符串的定义:
  1. Empty sequence is a regular sequence.
  2. If S is a regular sequence, then (S) and [S] are both regular sequences.
  3. If A and B are regular sequences, then AB is a regular sequence.

样例:

Sample Input

([(]

Sample Output

()[()]

解题思路:

这是一道 区间 dp (路径还原)

  • 状态方程 : dp[i][j] 代表使 区间 (i,j) 形成一个合法的字符串最少需要添加多的字符串?

    path[i][j] 代表添加最少的字符使 区间 (i,j) 形成一个合法的字符串的路径选择。

  • path[i][j] = 1 ,表示头尾。

    path[i][j] = k (k != 1 ) ,表示由 区间 (i,k)区间 (k+1 ,j) 而来。

  • 转移方程

    • 区间 (i,j) 可以由 区间 (i,k) + 区间 (k+1,j) 转移而来。
    • s[i] = s[j] 时,区间 (i,j) 也可以由 区间 (i+1,j1) 转移而来。(需要注意的是:当 i+1=j 时,直接 dp[i][j] = 0,否则会出现 i+1>j1 的情况)
  • 小思考:为什么最外层是枚举 区间长度,而不是直接枚举 区间端点 l,r 呢?

    • 答:因为我们转移的时候是从 小区间 转移到 大区间 的。
  • 最后答案:根据 path[i][j] 记录的值,用递归还原路径。(详情请看代码)

AC代码:

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

const int maxn = 105;
int dp[maxn][maxn],path[maxn][maxn];
char s[maxn];

void dfs(int l,int r){
    if(l > r) return;
    if(l == r){
        if(s[l] == '(' || s[l] == ')') cout << "()";
        else cout << "[]";
        return;
    }
    if(path[l][r] == -1){
        cout << s[l];//先输出左端点,
        dfs(l + 1,r - 1);//再输出中间,
        cout << s[r];//最后输出右端点。
    }
    else{
        int k = path[l][r];//分两部分输出。
        dfs(l,k);
        dfs(k + 1,r);
    }
}

int main(){
    int n;
    while(gets(s + 1)){
        n = strlen(s + 1);
        memset(dp,0x3f,sizeof(dp));
        memset(path,0,sizeof(path));
        for(int i = 1;i <= n;i++) dp[i][i] = 1;//初始化:自己当然初始化为 1,其他初始化为无穷大。
        for(int len = 2;len <= n;len++){
            for(int l = 1;l <= n - len + 1;l++){
                int r = len + l - 1;
                if((s[l] == '(' && s[r] == ')') || (s[l] == '[' && s[r] == ']')){
                    if(dp[l + 1][r - 1] < dp[l][r]){
                        dp[l][r] = dp[l + 1][r - 1];
                        path[l][r] = -1;
                    }
                    else if(l + 1 == r){
                        dp[l][r] = 0;
                        path[l][r] = -1;
                    }
                }
                for(int k = l;k < r;k++){
                    if(dp[l][k] + dp[k + 1][r] < dp[l][r]){
                        dp[l][r] = dp[l][k] + dp[k + 1][r];
                        path[l][r] = k;
                    }
                }
            }
        }
        dfs(1,n);
        cout << endl;
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页