***UVa-1626 Brackets sequence ACM解题报告(巧妙地递推+打印)经典的括号 dp题
2015-02-06 23:56
253 查看
这题绝对是经典的括号题,每次碰到括号我总是非常头疼,这次在小白的帮助下终于认真的学习了这题的解法。
这题的算法当时是dp,转移过程比较复杂,用d数组记录当前情况需要添加的括号数,分析d(i,j)的状态,有如下两种:
1.如果s[i]和s[j]配对,那么d(i,j)=d(i+1,j-1);
2.如果字符串有2个及以上的字符,可以将原本的字符串分为两个,转移为d(i,j)=d(i,k)+d(k+1,j);(配对的情况下也要考虑这种情况,因为1的转移未必是最优解,比如[][],如果只用1转移,就是][,要添2个括号,所以要进行2的转移)。
这题最坑爹的莫过于输入输出,第一个数下面要一个空行,每个input之间要一个空行,每个output之间要一个空行。
我学习小白书用的是递推的方法,倒叙枚举i,递推往往是比递归快,我要尽快学会写递推式子。
这题的算法当时是dp,转移过程比较复杂,用d数组记录当前情况需要添加的括号数,分析d(i,j)的状态,有如下两种:
1.如果s[i]和s[j]配对,那么d(i,j)=d(i+1,j-1);
2.如果字符串有2个及以上的字符,可以将原本的字符串分为两个,转移为d(i,j)=d(i,k)+d(k+1,j);(配对的情况下也要考虑这种情况,因为1的转移未必是最优解,比如[][],如果只用1转移,就是][,要添2个括号,所以要进行2的转移)。
这题最坑爹的莫过于输入输出,第一个数下面要一个空行,每个input之间要一个空行,每个output之间要一个空行。
我学习小白书用的是递推的方法,倒叙枚举i,递推往往是比递归快,我要尽快学会写递推式子。
#include<iostream> #include<cstdio> #include<cctype> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<queue> #include<map> #include<set> #include<sstream> #include<stack> using namespace std; #define MAX 105 typedef long long LL; const double pi=3.141592653589793; const int INF=1e9; const double inf=1e20; int d[105][105];//记录i-j之间需要添多少个括号。 char s[105]; bool match(char a,char b) { if(a=='('&&b==')') return true; else if(a=='['&&b==']') return true; return false; } void print(int i,int j) { if(i>j) return ; if(i==j) { if(s[i]=='('||s[i]==')') printf("()"); else if(s[i]=='['||s[i]==']') printf("[]"); return ; } int ans=d[i][j]; if(match(s[i],s[j])&&ans==d[i+1][j-1]) { printf("%c",s[i]); print(i+1,j-1); printf("%c",s[j]); return;//记得结束 } for(int k=i; k<j; k++) { if(ans==d[i][k]+d[k+1][j]) { print(i,k); print(k+1,j); return ;//这里一定要记得return } } } int main() { int n; scanf("%d",&n); getchar(); while(n--) { int count=0; char c; memset(d,0,sizeof(d));//每个input前有一个空行 memset(s,0,sizeof(s));//初始化s数组不能忘记 gets(s); gets(s); int len=strlen(s);//长度是len,一开始我写错写了n,错了好久。 for(int i=0; i<len; i++) d[i][i]=1; for(int i=len-2; i>=0; i--) { for(int j=i+1; j<len; j++) { d[i][j]=INF; if(match(s[i],s[j])) d[i][j]=min(d[i][j],d[i+1][j-1]);//两边可以配对,需要 for(int k=i; k<j; k++) d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]);//满足上面那个未必就是最优解,比如[][], //所以一定要尝试第二种把这个字符串分为两个字符串 } } print(0,len-1); printf("\n"); if(n) printf("\n");//坑死人不偿命啊,每个output之间还有个空行T_T,论认真读题的重要性 } return 0; }
相关文章推荐
- UVA1626 - Brackets sequence(区间DP--括号匹配+递归打印)
- uva 1626(动态规划起步第五天 LIS变形 括号匹配)
- 入门经典-习题7-1,109-uva208消防车-DFS,并查集,打印路径,利用set保存边,字典序,STL⭐⭐⭐⭐⭐复杂度:3
- UVA 1626 括号序列(区间dp)
- Brackets sequence UVA - 1626 (典型的区间dp+递归打印路径)
- UVA 1626 Brackets sequence dp:经典&&类似于三角剖分
- [UVa1626]括号序列
- UVA 1626 区间dp、打印路径
- 例题9-10 括号序列 UVa1626
- uva 1626 括号序列
- dp uva1626 括号序列
- NYOJ15 - UVA1626 括号匹配问题(区间dp)
- uva1626 poj 1141 Brackets Sequence 区间dp 打印路径
- POJ 1141 / UVa 1626 Brackets Sequence (区间DP&打印路径)
- UVA 673 括号的匹配——经典栈的应用
- UVA1626 DP经典
- NYOJ15 - UVA1626 括号匹配问题(dp)
- UVa 1626 括号序列(矩阵连乘)
- uva1626 括号序列
- Uva 1626,括号序列