标签:blog os io for ar 2014 amp log
题目大意:
给出一种不合法的括号序列,要求构造出一种合法的序列,使得填充的括号最少。
思路分析:
如果只要求输出最少的匹配括号的数量,那么就是简单的区间dp
dp[i][j]表示 i - j 之间已经合法了最少添加的括号数。
转移 就是 dp[i] [j] = min (dp[i+1][j]+1 , dp[ i+ 1] [ k -1 ] + dp[k+1] [j] (i k 位置的括号匹配))
其次我们要记录路径,你发现 如果 dp [i] [j] 是由 dp [i+1] [j] 转移过来的。那么第 i 个括号是一个多余存在的。所以首先我们就把这些位置标记。输出的时候不仅输出自己还要输出与之匹配的括号。。。
然后那些是通过后面有括号与之匹配而转移过来的。我们就可以把这两个位置标记。
那么这些位置就可以直接输出自己。
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; char str[205]; int dp[105][105]; int pre[105][105]; int mk[105]; void mark(int pos,int n) { if(pos>=n)return; if(pre[pos][n]==-1) { mark(pos+1,n); } else { mk[pos]=1; mk[pre[pos][n]]=1; mark(pos+1,pre[pos][n]-1); mark(pre[pos][n],n); } } int main() { scanf("%s",str+1); int n=strlen(str+1); memset(dp,0,sizeof dp); memset(mk,0,sizeof mk); memset(pre,-1,sizeof pre); for(int i=1; i<=n; i++)dp[i][i]=1; for(int i=n-1; i>=1; i--) { for(int j=i+1; j<=n; j++) { dp[i][j]=dp[i+1][j]+1; pre[i][j]=-1; for(int k=i+1; k<=j; k++) { if(str[i]=='('&&str[k]==')' || str[i]=='['&&str[k]==']') { if(dp[i+1][k-1]+dp[k+1][j]<dp[i][j]) { pre[i][j]=k; dp[i][j]=dp[i+1][k-1]+dp[k+1][j]; } } } } } mark(1,n); for(int i=1; i<=n; i++) if(mk[i]!=1) { if(str[i]=='(' || str[i]==')')printf("()"); else printf("[]"); } else { putchar(str[i]); } puts(""); return 0; }
POJ 1141 Brackets Sequence (区间dp 记录路径),布布扣,bubuko.com
POJ 1141 Brackets Sequence (区间dp 记录路径)
标签:blog os io for ar 2014 amp log
原文地址:http://blog.csdn.net/u010709592/article/details/38639037