timus1745题解
一、题目链接
http://acm.timus.ru/problem.aspx?space=1&num=1745
二、题意
给定$n$个由'('和')'组成的字符串,每个串最多只能使用$1$次,可以任意改变字符串之间的顺序,要求输出由这些字符串拼接起来可以得到的最大“正规括号序列”的长度,并输出选择方案。
三、思路
首先,这很显然需要$dp$。所以对字符串按照某种规则排序。容易想到的是,把左括号多的放前面,右括号多的放后面,然而,这只是理想的状态,稍微复杂的样例如下:
))()()(( )))(((( ()))(((()
对于这些复杂的样例,我们没法想清楚所以情况并逐一对其考虑排序,所以,这个地方留下一个坑,先参考这个博客里的神排序规则。
http://www.cnblogs.com/liulangye/archive/2013/10/02/3349523.html
然后,由于$\sum\limits_{i=1}^{n}|s_i| \le 10000$,$n \le 1000$,所以可以做01背包。
在每一个字符串中,记录它的左括号的个数$lb$和右括号的个数$lb$,同时再记录每个串里面已经匹配的最大长度$num$,并把$lb$和$rb$减去$num$。
$dp[i][j]$表示在前$i$个字符串里面选择若干个字符串且左括号个数比右括号个数exactly多$j$个所能获得的最大正规括号序列长度,那么,最终答案就是$dp[n][0]$。
如果采用“多推一”的$dp$方式,那么有:
如果$dp[i-1][j] \ne -1$,$dp[i][j]=max(dp[i][j],dp[i-1][j])$,
如果$dp[i-1][j+ns[i].rb-ns[i].lb] \ne -1$,$dp[i][j]=max(dp[i][j],dp[i-1][j+ns[i].rb-ns[i].lb]+ns[i].num+2*ns[i].rb)$
其中:$1 \le i \le n,0 \le j \le m$。
如果采用“一推多”的$dp$方式,那么有:
如果$dp[i][j] \ne -1$,$dp[i+1][j]=max(dp[i+1][j],dp[i][j])$,
$dp[i+1][j-ns[i].rb+ns[i].lb]=max(dp[i+1][j-ns[i].rb+ns[i].lb],dp[i][j]+ns[i].num+2*ns[i].rb)$,
其中:$0 \le i < n,0 \le j \le m$。
上式中的$m=\sum\limits_{i=1}^{n}|s_i|$。
要注意的是:
1、在一开始输入的时候,要根据所采用的$dp$姿势来确定下标的起点。
2、从个人感觉来看,第一种"多推一"的$dp$姿势状态转移没那么直观,但是找路径更加直观;第二种"一推多"的$dp$姿势状态转移更加直观,但是找路径没那么直观。
2、无论那种$dp$姿势,无论当前括号序列有没有取,都需要记录父节点。
3、要记录路径,所以在状态转移的时候,无论当前“背包”是选还是不选,都应该设置父节点,否则,肯定会错。
4、由于$dp[i][j]$表示在前$i$个字符串里面选择若干个字符串且左括号个数比右括号个数exactly多$j$个所能获得的最大正规括号序列长度,所以一开始要把$dp$数组初始化为$-1$。在初始状态中,只有$dp[0][0]$是合法的,即$dp[0][0]=0$。
5、在"一推多"的$dp$状态转移代码中,有这么一个判断条件$j-ns[i].rb>=0$,这个条件一定不能写成$j-ns[i].rb+ns[i].lb>=0$,因为题目中说明了,在“正规括号序列”的任意前缀中,左括号的数量都不小于右括号的数量。如果写成了第二种条件,那么“))()((”这种样例也会满足条件。
四、代码
1、“一推多”的$dp$
#include<bits/stdc++.h>
using namespace std;
struct node{
string s;
int id,lb,rb,num;
}ns[];
int func(const node& a){
int t=a.lb-a.rb;
?:t/abs(t);
}
bool cmp(const node& a,const node& b){
int lf=func(a),rf=func(b);
&&rf==)return a.rb<b.rb;
&&rf==-)return a.lb>b.lb;
else return lf>rf;
}
][],ans[],acnt;
][];
int main(){
// freopen("input.txt","r",stdin);
ios::sync_with_stdio();
cin.tie();
;
cin>>n;
;i<n;++i){
cin>>ns[i].s;
m+=ns[i].s.size();
ns[i].id=i+;
ns[i].lb=ns[i].rb=ns[i].num=;
stack<char> st;
;j<ns[i].s.size();++j){
if(ns[i].s[j]=='(')ns[i].lb++;
else ns[i].rb++;
if(ns[i].s[j]=='(')st.push('(');
;
}
ns[i].lb-=ns[i].num/;
ns[i].rb-=ns[i].num/;
}
sort(ns,ns+n,cmp);
memset(dp,-,sizeof(dp));
memset(path,-,sizeof(path));
dp[][]=;
;i<n;++i){
;j<=m;++j){
)continue;
][j]<dp[i][j]){
dp[i+][j]=dp[i][j];
path[i+][j]=-;
}
&&j-ns[i].rb+ns[i].lb<=m
&&dp[i+][j-ns[i].rb+ns[i].lb]<dp[i][j]+ns[i].num+*ns[i].rb){
dp[i+][j-ns[i].rb+ns[i].lb]=dp[i][j]+ns[i].num+*ns[i].rb;
path[i+][j-ns[i].rb+ns[i].lb]=j;
}
}
}
acnt=;
;i>;--i){
){
ans[acnt++]=ns[i-].id;
j=path[i][j];
}
}
cout<<(dp[n][]==-?:dp[n][])<<" "<<acnt<<endl;
;i>=;--i)cout<<ans[i]<<];
;
}
2、"多推一"的$dp$
#include<bits/stdc++.h>
using namespace std;
struct node{
string s;
int id,lb,rb,num;
}ns[];
int func(const node& a){
int t=a.lb-a.rb;
?:t/abs(t);
}
bool cmp(const node& a,const node& b){
int lf=func(a),rf=func(b);
&&rf==)return a.rb<b.rb;
&&rf==-)return a.lb>b.lb;
else return lf>rf;
}
][],ans[],acnt;
][];
int main(){
// freopen("input.txt","r",stdin);
ios::sync_with_stdio();
cin.tie();
;
cin>>n;
;i<=n;++i){
cin>>ns[i].s;
m+=ns[i].s.size();
ns[i].id=i;
ns[i].lb=ns[i].rb=ns[i].num=;
stack<char> st;
;j<ns[i].s.size();++j){
if(ns[i].s[j]=='(')ns[i].lb++;
else ns[i].rb++;
if(ns[i].s[j]=='(')st.push('(');
;
}
ns[i].lb-=ns[i].num/;
ns[i].rb-=ns[i].num/;
}
sort(ns+,ns+n+,cmp);
memset(dp,-,sizeof(dp));
memset(path,-,sizeof(path));
dp[][]=;
;i<=n;++i){
;j<=m;++j){
][j]!=-&&dp[i][j]<dp[i-][j]){
dp[i][j]=dp[i-][j];
path[i][j]=-;
}
&&j+ns[i].rb-ns[i].lb<=m
&&dp[i-][j+ns[i].rb-ns[i].lb]!=-
&&dp[i][j]<dp[i-][j+ns[i].rb-ns[i].lb]+ns[i].num+*ns[i].rb){
dp[i][j]=dp[i-][j+ns[i].rb-ns[i].lb]+ns[i].num+*ns[i].rb;
path[i][j]=j+ns[i].rb-ns[i].lb;
}
}
}
acnt=;
;i>;--i){
){
ans[acnt++]=ns[i].id;
j=path[i][j];
}
}
cout<<(dp[n][]==-?:dp[n][])<<" "<<acnt<<endl;
;i>=;--i)cout<<ans[i]<<];
;
}
timus1745题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- jQuery之阻止默认事件以及解除阻止
大家都知道e.preventDefault()可以阻止默认时间,例如提交功能,但是怎么解除呢?以下参考于网络: 可以使用removeEventListener来移除.但是条件是addEventList ...
- HDU 1254 推箱子(BFS)
Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不 ...
- vue 移动端添加 时间日期选择器
效果: index.vue <template> <div class="user-wrap" style="padding-bottom: 0;tex ...
- Port of FreeModbus to STM32
/********************************************************************************* * Port of FreeMod ...
- Windows 7 SP1 多国语言包(MUI language packs)官方下载
为了装一款 Gal Game (为毛不是装 H-Game?),使用 APP 还是太辛苦了,反正相信童鞋们也都用上“瘟妻”了嘛,装个日文的语言包基本上就可以解决问题了.大家都知道只有旗舰版(Wind ...
- ElasticSearch(五):简单的ElasticSearch搜索功能
这里主要是一些简单的ElasticSearch的搜索功能,复杂的搜索,比如过滤,聚合等以后单独在写 1. 搜索全部 GET book/_search 直接搜索全部,下面是对搜索结果的详细介绍:默认情况 ...
- 为什么我们不应该使用微信或者 QQ 作为团队协作的 IM 工具?
如果你的团队没有觉得微信是低效的团队 IM 工具,那只有两种可能: 团队成员很少使用微信进行私人的生活和娱乐. 你就是一个低效的团队,而且还不自知. 本文内容 微信,连接一切 每个人都有微信 微信,低 ...
- pylot压力测试工具
博客搬家了,欢迎大家关注,https://bobjin.com 由于版本的兼容性问题,现在在windows下搭建pylot+matplotlib压力测试环境真的会令人吃尽苦头.这是因为,pylot从2 ...
- hdu1081 DP类最大子段和(二维压缩+前缀和数组/树状数组计数)
题意:给出一个 n * n 的数字矩阵,问最大子矩阵和是多少. 由于和最长子段和问题类似,一开始想到的就是 DP ,一开始我准备用两个循环进行 DP ,对于每一个 (i,j) ,考察(i - 1,j) ...
- 93服务器上获取json数据
jdf u -p上传html文件,上传到page域名下:jdf u 上传css和js 上传到misc域名下: json数据放在html下,因为ajax请求是按照html路径走的,所以json数据放在h ...