poj 1141 Brackets Sequence 【DP&&备忘录】
2009-08-24 23:40
363 查看
题目如下:
Description
Let us define a regular brackets sequence in the following way:
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.
For example, all of the following sequences of characters are regular brackets sequences:
(), [], (()), ([]), ()[], ()[()]
And all of the following character sequences are not:
(, [, ), )(, ([)], ([(]
Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input
The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.
Output
Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.
Sample Input
Sample Output
Description
Let us define a regular brackets sequence in the following way:
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.
For example, all of the following sequences of characters are regular brackets sequences:
(), [], (()), ([]), ()[], ()[()]
And all of the following character sequences are not:
(, [, ), )(, ([)], ([(]
Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input
The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.
Output
Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.
Sample Input
([(]
Sample Output
()[()]
解答:
用char *str 记录符号,Int * *state 记录符号数,state[i][j]表示str[i]……str[j]补全括号之后的括号数;
用string * *ans表示补全括号之后的串,ans[i][j]表示str[i]……str[j]补全括号之后的括号串
主要注意两句话:
第一句:If A and B are regular sequences, then AB is a regular sequence
那我们可以得出如下状态转移方程:
state[i][j]=min(state[i][k]+state[k+1][j]) (i<=k<=j)
ans[i][j]=ans[i][k]+ans[k+1][j]
第二句:If S is a regular sequence, then (S) and [S] are both regular sequences.
我们可以得到:
state[i][j]=min(state[i][j],state[i+1][j-1]+2) if(match(str[i],str[j]))
ans[i][j]=str[i]+ans[i+1][j-1]+str[j]
值得注意的是初始化数据:
state[i][i]=2
state[i][j]=0 if(i>j);
以下是代码:
代码1是用了纯DP的方式
代码2用了备忘录。但是两者的基本思想都是一样的。
代码1:
#include<iostream> #include<string> using namespace std; #define M 105 int state[M][M]; string ans[M][M]; char str[M]; int n; bool Match(char x,char y) { if(x=='('&&y==')') return true; if(x=='['&&y==']') return true; return false; } void Init() { int i,j; for(i=0;i<=n;i++) for(j=0;j<=n;j++) { state[i][j]=0; ans[i][j]=""; } for(i=1;i<=n;i++) { state[i][i]=2; if(str[i]=='('||str[i]==')') ans[i][i]="()"; else ans[i][i]="[]"; } } void DP(){ int i,j,k; //以下的双重循环用得妙,我也是第一次这么用的,解决了对角线的求解问题。 for(j=1;j<n;j++) { for(i=1;i+j<=n;i++) { state[i][i+j]=10000; for(k=i;k<i+j;k++) { if(state[i][i+j]>(state[i][k]+state[k+1][i+j])) { state[i][i+j]=state[i][k]+state[k+1][i+j]; ans[i][i+j]=ans[i][k]+ans[k+1][i+j]; } } if(Match(str[i],str[i+j])) { if(state[i][i+j]>(state[i+1][j+i-1]+2)){ state[i][i+j]=state[i+1][j+i-1]+2; ans[i][i+j]=str[i]+ans[i+1][i+j-1]+str[i+j]; } } } } } int main() { cin>>str+1; n=strlen(str+1); Init(); DP(); cout<<ans[1] <<endl; return 0; }[/code]
代码2:
#include<iostream> #include<string> using namespace std; #define M 105 int state[M][M]; //表示第i个括号到j个括号,配对之后的括号数 string ans[M][M]; //表示第i个括号到j个括号,配对之后的符号串 char str[M]; int n; bool Match(char x,char y) { if(x=='('&&y==')') return true; if(x=='['&&y==']') return true; return false; } void Init() { int i,j; for(i=0;i<=n;i++) for(j=0;j<=n;j++) { state[i][j]=0; ans[i][j]=""; } for(i=1;i<=n;i++) { state[i][i]=2; if(str[i]=='('||str[i]==')') ans[i][i]="()"; else ans[i][i]="[]"; } } int DP(int i,int j){ int k; if(state[i][j]>0) return state[i][j]; if(i>j) return 0; int dist=99999; for(k=i;k<j;k++) { if(dist>DP(i,k)+DP(k+1,j)) { dist=DP(i,k)+DP(k+1,j); ans[i][j]=ans[i][k]+ans[k+1][j]; } if(Match(str[i],str[j])) { if(dist>DP(i+1,j-1)+2) { dist=state[i+1][j-1]+2; ans[i][j]=str[i]+ans[i+1][j-1]+str[j]; } } } state[i][j]=dist; return dist; } int main() { cin>>str+1; n=strlen(str+1); Init(); DP(1,n); cout<<ans[1] <<endl; return 0; }[/code]
相关文章推荐
- ★Uva 1626 && POJ 1141 Brackets sequence 详细题解(区间DP+递归打印)
- POJ 1141 / UVa 1626 Brackets Sequence (区间DP&打印路径)
- poj 1163 The Triangle &poj 3176 Cow Bowling (dp)
- POJ 3132 & ZOJ 2822 Sum of Different Primes(dp)
- POJ 3252 Round Numbers(数位dp && 记忆化搜索)
- poj 1141 区间dp
- POJ 1141 Brackets Sequence 区间dp
- poj 1141 括号匹配升级版 区间DP
- poj 2411 Mondriaan's Dream(状态压缩dp)
- POJ 1141(Bracket Sequence)-区间DP
- Uva 10559 & POJ 1390 Blocks 区间dp
- poj 2506 Tiling <dp+大数加法>
- poj-2411 Mondriaan's Dream (状态压缩dp)
- 简单区间dp(nyoj 746 && poj 2955)
- poj 1739 Tony's Tour 插头dp
- ACM: 动态规划 poj 1141
- ACM: DP训练好题 动态规划题 poj 1…
- POJ_2486_AppleTree(树状DP&&01背包)
- POJ 3252 Round Numbers(数位dp&记忆化搜索)
- poj 2241 && uva 437 The Tower of Babylon(DP)