【动规】POJ 1141 Brackets Sequence
来源:互联网 发布:日语软件测试工程师 编辑:程序博客网 时间:2024/09/21 06:17
题目
题目描述
Let us define a regular brackets sequence in the following way:
- Empty sequence is a regular sequence.
- If S is a regular sequence, then (S) and [S] are both regular sequences.
- 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.
输入
The input file contains at most 100 brackets (characters ‘(‘, ‘)’, ‘[’ and ‘]’) that are situated on a single line without any other characters among them.
输出
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.
样例输入
([(]
样例输出
()[()]
题目大意
输入一个由小括号或中括号组成的序列,用最少的操作使它变为正则括号表达式。
正则括号表达式:
- 空串是正则括号表达式
- 若S为正则括号表达式,那么(S)或[S]都是正则括号表达式
思路
最优方案计算
区间DP,设S[i]到S[j]添加
分两类:
- S[i]与S[j]能匹配:
f[i][j]=max(f[i][j],f[i+1][j−1]) - S[i]与S[j]不能匹配:
f[i][j]=max(f[i][k]+f[k+1][j]|i≤k<j)
对于第一种,S[i]与S[j]能匹配,自然可以不管它;
对于第二种,不能匹配时,就需要在之间找到一个断点k,分别处理i~k和k+1~j这一段,使它们变成正则括号表达式,那么S[i]和S[j]匹不匹配就无妨了。
注意上面加粗的几个字,当你根据我的分类写出下面的语句时,就WA了,好开心~
if(match(S[i],S[j])) /*...*/else /*...*/
如果这样,显然可以举出一个反例: [][]
程序会先判断S[1]和S[4],他们匹配,恩很好,所以f[i][j]=f[i+1][j-1],然后会发现f[i+1][j-1]是2(因为S[2]到S[3]需要加一个’[‘和一个’]’),于是答案是2,正确答案是0。
所以,无论else
去掉即可。
显然这个可以用记忆化递归实现,很好想,但是速度不是很快。
用递推的方式,就要赋初值,
最优方案输出
至于输出方案很简单,但是我就不告诉你。
设
在for循环找断点时即可得到pre[i][j]。
然后递归print,具体看程序。
代码
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 100char str[MAXN+5];int Len,f[MAXN+5][MAXN+5],pre[MAXN+5][MAXN+5];bool match(char x,char y)//括号x和y能否匹配{ return (x=='('&&y==')')||(x=='['&&y==']');}void print(int i,int j)//输出i~j区间方案{ if(i>j) return;//区间不存在 if(i==j)//长度为1的区间,怎样添加括号是确定的 { if(str[i]=='('||str[i]==')') printf("()"); else printf("[]"); } else if(pre[i][j])//说明之前分类的第二种更优 { print(i,pre[i][j]);//分段 print(pre[i][j]+1,j); } else//分类的第一种更优,即S[i]和S[j]在最终的答案中是需要匹配的 //不是能匹配就一定要输出,例如[][],S[1]和S[4]能匹配,但是不是最优 { printf("%c",str[i]); print(i+1,j-1); printf("%c",str[j]); }}int main(){ scanf("%s",str+1); Len=strlen(str+1); for(int i=1;i<=Len;i++) f[i][i]=1;//对于i~i,肯定要添加1个括号才能匹配 for(int i=Len-1;i>=1;i--) for(int j=i+1;j<=Len;j++)//区间DP模型 { f[i][j]=Len+1;//极大值,因为i~j最多可能放Len个括号 //让我很恶心的是之前赋Len就WA了= = if(match(str[i],str[j])) f[i][j]=min(f[i][j],f[i+1][j-1]);//能够匹配的情况 for(int k=i;k<j;k++)//不论能否匹配都要找一次,因为有可能有更好的 if(f[i][j]>f[i][k]+f[k+1][j]) { f[i][j]=f[i][k]+f[k+1][j]; pre[i][j]=k;//存断点 } } //printf("%d\n",f[1][Len]);//输出最少添加的括号数量 print(1,Len);puts("");}
- 【动规】POJ 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- Brackets Sequence--poj--1141
- poj 1141 Brackets Sequence
- poj 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- poj 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- poj 1141(Brackets Sequence)
- poj 1141 brackets sequence
- poj 1141 Brackets Sequence
- POJ 1141 Brackets Sequence
- poj 1141 Brackets Sequence
- poj 1141 brackets sequence
- POJ-1141-Brackets Sequence
- ES6 知识碎片1
- SVN版本update冲突详解
- 《分布式服务架构原理设计与实战》第8章敏捷开发笔记
- 内存泄露和内存溢出
- Android不使用图片框架,实现加载类似微博超长图片的技巧手法;
- 【动规】POJ 1141 Brackets Sequence
- Python 发送Email
- 初识JQuery,上课笔记
- 将查询的数据写到redis缓存中
- React Native 入门(二)
- C语言与VT100控制码编程
- PyTorch学习
- 2462: [BeiJing2011]矩阵模板
- make menuconfig出错,ncurses安装失败