poj-1141-Brackets sequence

题目链接:http://poj.org/problem?id=1141

题意:给定一括号序列,求出添加括号数最小的完整序列

解法:区间DP

定义dp[i][j]表示题目所给字符串s中从左至右字符i至j这一区间段括号序列构成完整序列所需添加的最小括号数;

根据i与j的大小对dp[i][j]进行初始化,i==j显然为1,i>j不符合定义中从左至右意为空序列即0,i<j因是取最小值则初值设为相对较大;

设阶段r为序列长度,状态为i为当前子序列的首指针,可得尾指针j=i+r;

可得状态转移方程f:dp[i][j]=min(dp[i][k](i~k区间),dp[k+1][j](k+1~j区间))  i<=k<j;

首先进行整体区间判断若(s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')即可得dp[i][j]=dp[i+1][j-1],再结合f得出dp[i][j];

因为题目要求输出所得完整序列故定义v[i][j]表示k的取值,k为分开i~j区间使dp[i][j]取最小值时的k,初始设为-1,递归输出即可;

#include<iostream>
#define N 10000000
using namespace std;
int dp[405][405],v[405][405],n;
string s;
void print(int l,int r){
    if(l>r) return;
    if(l==r){
        if(s[l]=='('||s[l]==')') cout<<"()";
        else cout<<"[]";
        return;
    }
    if(v[l][r]==-1){
        cout<<s[l];
        print(l+1,r-1);
        cout<<s[r];
    }
    else{
        int k=v[l][r];
        print(l,k);
        print(k+1,r);
    }
}
int main(){
    cin>>s;
    n=s.size();
    for(int i=0;i<205;i++)
    for(int j=0;j<205;j++){
        if(i==j) dp[i][j]=1;
        else {
                if(i>j) dp[i][j]=0;
                else dp[i][j]=N;
             }
        v[i][j]=-1;
    }
    for(int i=1;i<n;i++)
    for(int l=0;l+i<n;l++){
        int r=l+i;
        if((s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']')) dp[l][r]=dp[l+1][r-1];
        for(int j=l;j<r;j++){
        if(dp[l][r]>dp[l][j]+dp[j+1][r]){
        dp[l][r]=dp[l][j]+dp[j+1][r];
        v[l][r]=j;
        }
        }
    }
    print(0,n-1);
    cout<<endl;
return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/WELOTX/p/11296411.html