Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 23158 | Accepted: 6508 | Special Judge |
Description
Input
Output
Sample Input
([(]
Sample Output
()[()]
Source
经典区间DP。。。
/************************************************ * author:crazy_石头 * Pro:POJ 1141 Bracket Sequence * algorithm:区间DP * Time:110ms * Judge Status:Accepted * 解题思路: * dp[i][j]表示i~j间最少添加的字符能使所有括号匹配 * 那么当i和j匹配时,i~j的匹配数(dp[i][j])等于i+1~j-1 * 间的匹配数,即dp[i][j]=dp[i+1][j-1]; * 对于一般情况下,dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j] * 不断枚举k即可;找出最小值,用path记录路径,path=-1 * 表示i~j间括号得到匹配,输出递归输出即可; **************************************************/ #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> using namespace std; #define LL long long #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define ms(a,b) memset((a),(b),sizeof(a)) #define INF 1<<29 const int maxn=1500+5; const int maxm=32000+5; const LL mod=10000007 ; int dp[maxn][maxn];//i,j间最少添加几个字符串才匹配; int path[maxn][maxn]; char str[maxn]; inline bool match(int i,int j) { if((str[i]=='['&&str[j]==']')||(str[i]=='('&&str[j]==')')) return true; return false; } inline void output(int i,int j) { if(i>j)return; if(i==j) { if(str[i]=='['||str[i]==']')printf("[]"); else printf("()"); return ; } if(path[i][j]==-1)//path[i][j]==-1时表示匹配; { printf("%c",str[i]); output(i+1,j-1); printf("%c",str[j]); return ; } output(i,path[i][j]); output(path[i][j]+1,j); } inline void solve() { int len=strlen(str); rep(i,0,len-1) dp[i][i]=1; for(int i=1;i<len;i++) { for(int j=0;j+i<len;j++) { int t=j+i; dp[j][t]=INF; if(match(j,t)) { dp[j][t]=dp[j+1][t-1]; path[j][t]=-1; } for(int k=j;k<t;k++) { if(dp[j][t]>dp[j][k]+dp[k+1][t]) { dp[j][t]=dp[j][k]+dp[k+1][t]; path[j][t]=k; } } } } } int main() { while(gets(str)) { ms(dp,0); ms(path,0); int len=strlen(str)-1; solve(); output(0,len); printf("\n"); } return 0; }