#UVA1626#Brackets sequence(括号序列---石子归并类Dp)
2017-07-17 19:51
267 查看
题意:
给出T个字符串,仅由 '(' ')' '[' ']' 四种 字符组成,其中 ’()‘ '[]'为合法,'()[]' '([])' '[()]' 均为合法,而’[(])‘ '[)' 则为不合法状态
求最少添加多少个字符,使得字符串合法,输出合法的其中一种方案。(原始字符串字符不多于100个)
第一行为字符串数量。
样例输入:
1
([(]
样例输出:
()[()]
这题让人很容易想起之前做过的一道叫“剔除多余括号”的分治题,
当时是看外围那一圈是否可以去掉,
然后这题我就想分成两种情况,
第一,如果外围匹配,那么递归到里面
第二,长度大于一,无论是否匹配,都枚举中间分界点k,将字符串分为两段,分别递归求解
边界条件是长度为空时返回,为1时判断后匹配返回,用的是string类型,比较方便。
其实这个想法就像搜索一样,去把所有的方案都试过了,很显然会TLE,事实上也的确如此。
正解Dp:
令Dp[ i ][ j ]表示从 i 到 j 的字符串中需要添加括号的数量,
对于S[i]是否等于S[j],会产生同上分析的两种情况。
Dp[ i ][ j ] = min(Dp[ i ][ k ] + Dp[ k + 1 ][ j ]);
当S[i] == S[j]时,有Dp[ i ][ j ] = min(Dp[ i + 1 ][ j - 1 ], Dp[ i ][ j ]);
输出的时候同样分类讨论,根据Dp[ i ][ j ]中的值辅助输出结果,代码还是非常好懂的。
先给出TLE代码:
正解
Code:
给出T个字符串,仅由 '(' ')' '[' ']' 四种 字符组成,其中 ’()‘ '[]'为合法,'()[]' '([])' '[()]' 均为合法,而’[(])‘ '[)' 则为不合法状态
求最少添加多少个字符,使得字符串合法,输出合法的其中一种方案。(原始字符串字符不多于100个)
第一行为字符串数量。
样例输入:
1
([(]
样例输出:
()[()]
这题让人很容易想起之前做过的一道叫“剔除多余括号”的分治题,
当时是看外围那一圈是否可以去掉,
然后这题我就想分成两种情况,
第一,如果外围匹配,那么递归到里面
第二,长度大于一,无论是否匹配,都枚举中间分界点k,将字符串分为两段,分别递归求解
边界条件是长度为空时返回,为1时判断后匹配返回,用的是string类型,比较方便。
其实这个想法就像搜索一样,去把所有的方案都试过了,很显然会TLE,事实上也的确如此。
正解Dp:
令Dp[ i ][ j ]表示从 i 到 j 的字符串中需要添加括号的数量,
对于S[i]是否等于S[j],会产生同上分析的两种情况。
Dp[ i ][ j ] = min(Dp[ i ][ k ] + Dp[ k + 1 ][ j ]);
当S[i] == S[j]时,有Dp[ i ][ j ] = min(Dp[ i + 1 ][ j - 1 ], Dp[ i ][ j ]);
输出的时候同样分类讨论,根据Dp[ i ][ j ]中的值辅助输出结果,代码还是非常好懂的。
先给出TLE代码:
Status | Time limit exceeded |
---|---|
Length | 1380 |
Lang | C++ 5.3.0 |
Submitted | 2017-07-18 20:10:32 |
Shared |
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> using namespace std; string X; string Table[4] = {"(", ")", "[", "]"}; map<string, string>MAP; string Work(string S){ if(MAP.count(S))return MAP[S]; if(S.size() == 0) return string(""); if(S.size() == 1){ if(S == Table[0]) return S + Table[1]; else if(S == Table[1]) return Table[0] + S; else if(S == Table[2]) return S + Table[3]; else return Table[2] + S; } int len = S.size(); string rt, p; if((S[0] == '[' && S[len - 1] == ']') || (S[0] == '(' && S[len - 1] == ')')) rt = S[0] + Work(S.substr(1, len - 2)) + S[len - 1]; if(len >= 2) for(int i = 1; i < len; ++ i){//S = ")(" string lsub = S.substr(0, i); string l = Work(lsub);//"()" if(MAP.count(lsub) == 0) MAP[lsub] = l; string rsub = S.substr(i, len - i); string r = Work(rsub);//"()" if(MAP.count(rsub) == 0) MAP[rsub] = r; p = l + r;//"()()" if(p.size() < rt.size() || rt.size() == 0) rt = p; } return rt; } int main(){ int T; scanf("%d", &T); while(T --){ cin >> X; string rt = Work(X); cout << rt << endl; } return 0; }
正解
Code:
Status | Accepted |
---|---|
Time | 390ms |
Length | 1641 |
Lang | C++11 5.3.0 |
Submitted | 2017-07-17 19:48:59 |
Shared |
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int Max = 100; const int INF = 0x3f3f3f3f; int N; char S[Max + 5]; int Dp[Max + 5][Max + 5]; bool Match(int a, int b){ if((S[a] == '(' && S[b] == ')') || (S[a] == '[' && S[b] == ']')) ret 4000 urn 1; return 0; } void Print(int l, int r){ if(l > r) return ; if(l == r){ if(S[l] == '(' || S[l] == ')') printf("()"); else printf("[]"); return ; } if(Match(l, r) && Dp[l][r] == Dp[l + 1][r - 1]){ printf("%c", S[l]); Print(l + 1, r - 1); printf("%c", S[r]); return ; } for(int k = l; k < r; ++ k) if(Dp[l][r] == Dp[l][k] + Dp[k + 1][r]){ Print(l, k); Print(k + 1, r); return ; } } int main(){ int T, flg = 0; scanf("%d", &T); getchar(); while(T --){ gets(S); gets(S); N = strlen(S); if(! N){ if(flg ++) putchar(10); putchar(10); continue; } for(int i = 0; i < N; ++ i) Dp[i][i] = 1; for(int i = N - 1; i >= 0; -- i){ for(int j = i + 1; j < N; ++ j){ Dp[i][j] = INF; if(Match(i, j)) Dp[i][j] = min(Dp[i][j], Dp[i + 1][j - 1]); for(int k = i; k < j; ++ k) Dp[i][j] = min(Dp[i][j], Dp[i][k] + Dp[k + 1][j]); } } if(flg ++) putchar(10); Print(0, N - 1); putchar(10); } return 0; }
相关文章推荐
- 区间dp基础(石子归并,括号匹配,整数划分。。。)
- 区间DP:POJ 2955括号匹配 + NYOJ 737 石子归并(一) + No.312 Burst Balloons
- 区间dp模型(石子归并,括号匹配,整数划分)
- 区间dp模型(石子归并,括号匹配,整数划分)
- 区间dp模型(石子归并,括号匹配,整数划分)
- 【codevs1048】【codevs1154&&06TG】石子归并、能量项链,序列dp的典型题目
- 【算法学习笔记】84.序列DP 松弛+代价处理 CODE_VS 1048 石子归并
- 【codevs1048】【codevs1154&&06TG】石子归并、能量项链,序列dp的典型题目
- 区间dp模型(石子归并,括号匹配,整数划分)入门经典三道题
- CSUOJ - 1592石子归并(区间DP)
- CodeVS2102 石子归并 2 解题报告【区间DP】
- CSU 1592 石子归并(区间dp)
- CSU 1592 石子归并 相邻操作Dp问题
- 51nod oj 1021 石子归并【区间dp】
- 1021 石子归并 dp
- [codevs1048]石子归并 区间dp经典
- poj1141 Brackets Sequence( 括号序列)(dp)
- 51nod 1021 石子归并 dp
- 1021 石子归并(区间DP)
- 【日常学习】【区间DP】codevs1048 石子归并题解