链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4501

题意:

定义如下正规括号序列(字符串):
1.空序列是正规括号序列。
2.如果S是正规括号序列,那么(S)和[S]也是正规括号序列。
3.如果A和B都是正规括号序列,那么AB也是正规括号序列。
输入一个长度不超过100的,由“(”、“)”、“[”、“]”构成的序列,添加尽量少的括号,得到一个正规序列。
如有多解,输出任意一个序列即可。

分析:

设串S至少需要增加d(S)个括号,转移如下:
1.如果S形如(S′)或者[S′],转移到d(S′)。
2.如果S至少有两个字符,则可以分成AB,转移到d(A)+d(B)。
边界是:S为空时d(S)=0,S为单字符时d(S)=1。
注意:不管S是否满足第一种,都要尝试第二种转移,否则“[][]”会转移到“][”,然后就只能加两个括号了。
设d(i,j)表示子串S[i~j]至少需要添加几个括号。
对于第一种,状态转移方程为:d(i,j) = d(i+1, j-1)。
对于第二种,状态转移方程为:d(i,j) = min{d(i, k) + d(k+1, j) | i ≤ k < j}。
可以在打印解的时候重新检查一下哪个决策最好。
最后,这题的输入输出有点坑。。。

代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int UP = + ;
char s[UP];
int d[UP][UP]; // d[L][R]表示子串s[L~R]至少需要添加几个括号 bool match(char L, char R){
return (L == '(' && R == ')') || (L == '[' && R == ']');
} void dynamic_programming(int len){
for(int i = ; i < len; i++){
d[i][i] = ;
d[i+][i] = ;
}
for(int L = len - ; L >= ; L--){
for(int R = L + ; R < len; R++){
int& v = d[L][R];
v = match(s[L], s[R]) ? d[L+][R-] : ;
for(int M = L; M < R; M++) v = min(v, d[L][M] + d[M+][R]);
}
}
} void output(int L, int R){
if(L > R) return;
if(L == R){
if(s[L] == '(' || s[L] == ')') printf("()");
else printf("[]");
return;
}
int ans = d[L][R];
if(match(s[L], s[R]) && d[L+][R-] == ans){
printf("%c", s[L]); output(L+, R-); printf("%c", s[R]);
return;
}
for(int M = L; M < R; M++) if(d[L][M] + d[M+][R] == ans){
output(L, M); output(M+, R);
return;
}
} int main(){
int T;
scanf("%d", &T);
getchar();
while(T--){
gets(s); gets(s);
int len = strlen(s);
dynamic_programming(len);
output(, len - ); printf("\n");
if(T) printf("\n");
}
return ;
}

最后,再贴一下我一开始的代码,状态的转移有点不同:当s[L]与s[M]不匹配时,d(L,M)转移到d(L+1,M)+1。

递推写法:

 #include <cstdio>
#include <cstring> const int UP = + ;
char s[UP];
int d[UP][UP], ans[UP][UP]; int diff(int L, int R){
if(s[L] == '(') return s[R] != ')';
if(s[L] == '[') return s[R] != ']';
return ;
} void dynamic_programming(int len){
for(int i = ; i < len; i++){
d[i][i] = ;
d[i+][i] = ;
}
for(int L = len - ; L >= ; L--){
for(int R = L + ; R < len; R++){
d[L][R] = ;
for(int M = L; M <= R; M++){
int f = diff(L, M);
int v = f + d[L+][M-+f] + d[M+][R];
if(d[L][R] > v){
d[L][R] = v;
ans[L][R] = M;
}
}
}
}
} void output(int L, int R){
if(L > R) return;
if(L == R){
if(s[L] == '(' || s[L] == ')') printf("()");
else printf("[]");
return;
}
int M = ans[L][R];
if(L == M){
output(L, M); output(M+, R);
return;
}
printf("%c", s[L]);
if(!diff(L, M)) output(L+, M-), printf("%c", s[M]);
else output(L+, M), printf("%c", s[L] == '(' ? ')' : ']');
output(M+, R);
} int main(){
int T;
scanf("%d", &T);
getchar();
while(T--){
gets(s); gets(s);
int len = strlen(s);
dynamic_programming(len);
output(, len - ); printf("\n");
if(T) printf("\n");
}
return ;
}

记忆化写法(比递推写法慢几倍):

 #include <cstdio>
#include <cstring> const int INF = 0x3f3f3f3f;
const int UP = + ;
int d[UP][UP], ans[UP][UP];
char s[UP]; int diff(int L, int R){
if(s[L] == '(') return s[R] != ')';
if(s[L] == '[') return s[R] != ']';
return ;
} int dp(int L, int R){
if(L > R) return ;
if(L == R) return ;
int& v = d[L][R];
if(v != INF) return v; for(int M = L; M <= R; M++){
int f = diff(L, M);
int res = f + dp(L+, M-+f) + dp(M+, R);
if(v > res){
v = res;
ans[L][R] = M;
}
}
return v;
} void output(int L, int R){
if(L > R) return;
if(L == R){
if(s[L] == '(' || s[L] == ')') printf("()");
else printf("[]");
return;
}
int M = ans[L][R];
if(L == M){
output(L, M); output(M+, R);
return;
}
printf("%c", s[L]);
if(!diff(L, M)) output(L+, M-), printf("%c", s[M]);
else output(L+, M), printf("%c", s[L] == '(' ? ')' : ']');
output(M+, R);
} int main(){
int T;
scanf("%d", &T);
getchar();
while(T--){
gets(s); gets(s);
memset(d, INF, sizeof(d));
dp(, strlen(s) - );
output(, strlen(s) - );
printf("\n");
if(T) printf("\n");
}
return ;
}

UVa 1626 - Brackets sequence(区间DP)的更多相关文章

  1. UVA 1626 Brackets sequence 区间DP

    题意:给定一个括号序列,将它变成匹配的括号序列,可能多种答案任意输出一组即可.注意:输入可能是空串. 思路:D[i][j]表示区间[i, j]至少需要匹配的括号数,转移方程D[i][j] = min( ...

  2. POJ 1141 Brackets Sequence(区间DP, DP打印路径)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  3. poj 1141 Brackets Sequence 区间dp,分块记录

    Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35049   Accepted: 101 ...

  4. UVA - 1626 Brackets sequence (区间dp)

    题意:给定一个串,可能空串,或由'[',']','(',')'组成.问使其平衡所需添加最少的字符数,并打印平衡后的串. 分析:dp[i][j]表示区间(i,j)最少需添加的字符数. 1.递推. #in ...

  5. UVA 1626 Brackets sequence(括号匹配 + 区间DP)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105116#problem/E 题意:添加最少的括号,让每个括号都能匹配并输出 分析:dp ...

  6. UVa 1626 Brackets sequence (动态规划)

    题意:用最少的括号将给定的字符串匹配,输出最优解.可能有空行. 思路:dp. dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么 如果区间左边是(或[,表示可以和右边的字符串匹配, ...

  7. poj 1141 Brackets Sequence (区间dp)

    题目链接:http://poj.org/problem?id=1141 题解:求已知子串最短的括号完备的全序列 代码: #include<iostream> #include<cst ...

  8. Ural 1183 Brackets Sequence(区间DP+记忆化搜索)

    题目地址:Ural 1183 最终把这题给A了.. .拖拉了好长时间,.. 自己想还是想不出来,正好紫书上有这题. d[i][j]为输入序列从下标i到下标j最少须要加多少括号才干成为合法序列.0< ...

  9. poj 1141 Brackets Sequence ( 区间dp+输出方案 )

    http://blog.csdn.net/cc_again/article/details/10169643 http://blog.csdn.net/lijiecsu/article/details ...

随机推荐

  1. liunx下在线升级python到2.7版本

    因开发nodejs中间用到了node-gyp模块,此模块需2.X最新版本,所以升级服务器python版本 亲测成功 python 升级步骤#1.which python 查询python的位置/usr ...

  2. (原创).Net将EF运用于Oralce一 准备工作

    网上有很多EF运用于Oracle的博文,但是找了半天发现大多数博文大都语焉不详,于是决定自己折腾. 首先我的开发工具为vs2010,那么最适用于VS2010的EF版本为多少呢?答案是EF5.我在Sta ...

  3. Nginx - 简易图片服务器

    安装 主要使用Nginx和vsftpd. 安装方面可以直接从nginx官网上下载,或者... yum install nginx 如果没有yum源则需要自行添加再进行install. yum inst ...

  4. sublime快捷键大全(转)

    文件 File 新建文件 Ctrl + N 打开文件 Ctrl + O 打开最近关闭的文件 Ctrl + Shift + T 保存 Ctrl + S 另存为… Ctrl + Shift + S 关闭文 ...

  5. 一些在线开发手册api文档收藏

    java JavaSE8 api:https://docs.oracle.com/javase/8/docs/api/ JavaSE7 api:http://docs.oracle.com/javas ...

  6. linux 安装php扩展swoole redis

    本文讲的是已经有redis.so 和swoole.so文件的情况 我的环境是xampp php的扩展目录为 /opt/lampp/lib/php/extensions/no-debug-non-zts ...

  7. 二、NAT(地址转换模式)

    刚刚我们说到,如果你的网络ip资源紧缺,但是你又希望你的虚拟机能够联网,这时候NAT模式是最好的选择.NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网.其网络结构如下图所示: NA ...

  8. vue-i18n国际化实例

    demo 场景需求分析 需求很简单,左上角 ''网易云音乐''就是一个中英文切换的按钮,点击弹出提示框,确认切换语言后,实现英文版本. 切换成英文版本: 三.实现国际化 1.我们得先有开发环境,先有项 ...

  9. input框中如何添加搜索

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. FCKeditor文本编辑器的使用方法

    FCKeditor是一个功能强大支持所见即所得功能的文本编辑器,可以为用户提供微软office软件一样的在线文档编辑服务. 它不需要安装任何形式的客户端,兼容绝大多数主流浏览器,支持ASP.Net.A ...