Brackets Sequence POJ - 1141(算是区间dp入门一道不错的题?

题目大意:

用以下方式定义合法的括号字符串
1.空串是合法的
2. 如果 S 是合法的, 那么 (S)[S] 也都是合法的
3. 如果 AB 是合法的, 那么 AB 是一个合法的字符串.
举个栗子, 下列字符串都是合法的括号字符串:(),[],(()),([]),()[],()[()]
下面这些不是:(,[,),)(,([)],([(]
给出一个由字符'(', ')', '[', 和']'构成的字符串. 你的任务是找出一个最短的合法字符串,使得给出的字符串是这个字符串的子序列。对于字符串a1 a2 ... an, b1 b2 ... bm 当且仅当对于1 ≤ i1 < i2 < ... < in ≤ m, 使得对于所有1 ≤ j ≤ n,aj = bij 时, ajbi 的子序列
输入一个只含有'(', ')', '[', ']'字符的字符串,字符串的最大长度是100
输出一个最短的合法字符串,使得输入的字符串是输出字符串的子序列(可能有多种情况,任意一种情况都可以)

分析:

其实光是求序列里最长的合法的串的长度还是挺简单的,设 dp[i][j] 表示序列从 ij 这一段想要变成合法的括号序列所需要的最少操作次数,这里直接上状态转移方程:

{dp[i][j]=min(dp[i][j],dp[i+1][j1])((s[i]==(ands[j]==))or(s[i]==[ands[j]==]))dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])

为了用递归输出方案,还要记录一下每一段内的元素是在哪里分成两截的,即左半部分能构成合法括号串,右半部分能构成合法括号串,如果为-1,则表示该段本身合法,无需分段输出,同时在输出过程中还要记得将序列补全

#include<iostream> #include<string> #include<cstring> using namespace std; const int MAXN = 2e3; const int INF = 1e9; string s; int dp[MAXN][MAXN],pos[MAXN][MAXN]; void print(int i,int j){ if(i > j)return; if(i == j){ if(s[i] == '(' || s[i] == ')')cout << "()"; else if(s[i] == '[' || s[i] == ']')cout << "[]"; return; } if(pos[i][j] == -1){ cout << s[i]; print(i + 1,j - 1); cout << s[j]; } else if(pos[i][j] != -1){ print(i,pos[i][j]); print(pos[i][j] + 1,j); } } int main(){ while(getline(cin,s)){ if(s.size() == 0){ puts(""); continue; } memset(dp,0,sizeof dp); memset(pos,0,sizeof pos); for(int i = 0; i < s.size(); i++){ dp[i][i] = 1; } for(int l = 1; l < s.size(); l++){ for(int i = 0; i + l < s.size(); i++){ int j = i + l; dp[i][j] = INF; if(s[i] == '(' && s[j] == ')'){ dp[i][j] = min(dp[i][j],dp[i + 1][j - 1]); pos[i][j] = -1; } else if(s[i] == '[' && s[j] == ']'){ dp[i][j] = min(dp[i][j],dp[i + 1][j - 1]); pos[i][j] = -1; } for(int k = i; k < j; k++){ if(dp[i][j] > dp[i][k] + dp[k + 1][j]){ dp[i][j] = dp[i][k] + dp[k + 1][j]; pos[i][j] = k; } } } } print(0,s.size() - 1); puts(""); } }

__EOF__

本文作者Never Gonna Give You Up!
本文链接https://www.cnblogs.com/CZ-9/p/16567426.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   腾云今天首飞了吗  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示