标签:
题意:
给你一个括号序列(有中小括号),求出以给定序列为子序列的最小合法括号序列。
分析:
非常经典,以前做过相似一道题,用区间dp,但怎么把这个序列求出来没想出来。
dp[i][j]表示区间i-j是序列合法要增加括号的最小数量,并pos[i][j]表示i-j在哪个位置断开最小,最后通过递归位置打印出答案。
此题序列可能是空串。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int dp[110][110],pos[110][110],len; char s[110]; void solve(){ memset(dp,0,sizeof(dp)); for(int i=0;i<len;++i) dp[i][i]=1; for(int l=1;l<len;++l) for(int i=0;i+l<len;++i){ int j=i+l; int minv=INF; for(int k=i;k<j;++k){ if(dp[i][k]+dp[k+1][j]<minv) { minv=dp[i][k]+dp[k+1][j]; pos[i][j]=k; } } if(s[i]==‘(‘&&s[j]==‘)‘||s[i]==‘[‘&&s[j]==‘]‘){ if(dp[i+1][j-1]<minv){ minv=dp[i+1][j-1]; pos[i][j]=-1; } } dp[i][j]=minv; } } void dfs(int l,int r){ if(l>r)return; if(l==r){ if(s[l]==‘(‘||s[l]==‘)‘) printf("()"); else printf("[]"); } else{ if(pos[l][r]>=0){ dfs(l,pos[l][r]); dfs(pos[l][r]+1,r); } else{ if(s[l]==‘(‘){ printf("("); dfs(l+1,r-1); printf(")"); } else{ printf("["); dfs(l+1,r-1); printf("]"); } } } } int main() { int ca=0,t; scanf("%d",&t); getchar(); while(t--){ gets(s); gets(s); memset(pos,-1,sizeof(pos)); len=strlen(s); if(len==0) { printf("\n"); if(t)printf("\n"); continue; } solve(); dfs(0,len-1); printf("\n"); if(t)printf("\n"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zsf123/p/4872457.html