@description@

卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很高的选手迷之超时。

普遍认为卡常数是埃及人Qa'a及后人发现的常数。也可认为是卡普雷卡尔(Kaprekar)常数的别称。主要用于求解括号序列问题。

据考证,卡(Qa'a)是古埃及第一王朝的最后一位法老。他发现并研究了一种常数,后世以他的名字叫做卡常数。卡特兰数的起源也是因为卡的后人与特兰克斯结婚,生下来的孩子就叫卡特兰,而他只是发表了祖传的家书而已。Sereja也是卡的后人,提出括号序列问题,也是从家书里得到的资料。然而Sereja为了不让这个秘密公开,于是隐瞒了这道题的真正做法。可是由于卡的后人不是各个都像卡特兰一样爱慕虚荣,这一算法也无法找到。“欲见贤人而不以其道,犹欲其入而闭之门也”。卡之常数的奥秘,需要以一颗诚心去追寻。

【以上全是瞎 BB,不过还蛮有意思的 www】

现给定n个括号序列,你需要选择若干序列,将它们按一定的顺序从左往右拼接起来,得到一个合法的括号序列。

显然,这个问题可以用卡常数解决,为了检验你是否会卡常数,请写一个程序,计算可以得到的合法的括号序列的长度的最大值。

input

第一行包含一个正整数n(1<=n<=300),表示括号序列的个数。

接下来n行,每行一个长度在[1,300]之间的括号序列,仅由小括号构成。

output

输出一行一个整数,即最大长度,注意你可以一个序列也不选,此时长度为0。

sample input

3

())

((()

)()

sample output

10

**sample explain **:

按{2,1,3}的顺序拼接得到((()()))(),总长度为10。

@solution@

首先有个小性质:假如在不拼接的情况,一个括号已经有了匹配,那么拼接后这个括号的匹配不会变化。可以根据我们做括号匹配的过程理解这个性质。

所以基于此,我们可以把串中能匹配的括号先匹配完,剩下的部分一定是形如 “)))))....))(((....(((” 的样子。

我们将这部分记为 (p, q),其中 p 是 ')' 的个数,q 是 '(' 的个数。

考虑选了一些括号以后,怎么排列它们是最优的。可以用贪心来解决。

我们采用交换论证的方法来寻找排列方法。

假如 a,b 是相邻的且 a 在 b 前面,我们可以先将 a 的 '(' 和 b 的 ')' 匹配完,剩下新的一个 “)))(((” 型的串。

感性理解一下,我们应该剩下的东西越少越好。又因为 a 与 b 的括号总数不变,我们应该让 a 与 b 匹配尽量多的括号。匹配的括号个数就应该 \(=\min\{(个数,)个数\}\)

所以如果 \(\min\{a的(个数,b)个数\} > \min\{b的(个数, a的)个数\}\),则 a 就排在 b 前面。

可以发现上面那个东西是一直存在的,不会因为我们选的括号不同而变化。

所以我们可以先按照上面的法则排序,然后作一个简单的 dp 就可以了。

dp 的定义,以及状态转移留作习题。

@accepted code@

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 300;
const int INF = 1<<30;
struct node{
int p, q;
int num;
}a[MAXN + 5];// p -> ')', q -> '('
bool operator < (node a, node b) {
return min(a.q, b.p) > min(a.p, b.q);
}
char s[MAXN + 5];
int dp[2][MAXN*MAXN + 5];
int main() {
int n; scanf("%d", &n);
for(int i=1;i<=n;i++) {
scanf("%s", s);
int len = strlen(s);
for(int j=0;j<len;j++) {
if( s[j] == '(' ) a[i].q++;
else {
if( !a[i].q ) a[i].p++;
else a[i].q--, a[i].num += 2;
}
}
}
int tot = 0; sort(a+1, a+n+1);
for(int i=1;i<=n;i++) {
for(int j=0;j<=tot;j++)
dp[i&1][j] = dp[i&1^1][j];
for(int j=tot+1;j<=tot+a[i].q;j++)
dp[i&1][j] = -INF;
for(int j=a[i].p;j<=tot;j++)
dp[i&1][j-a[i].p+a[i].q] = max(dp[i&1][j-a[i].p+a[i].q], dp[i&1^1][j]+2*a[i].p+a[i].num);
tot += a[i].q;
}
printf("%d\n", dp[n&1][0]);
}

@details@

这道题让我想起了多校赛的某道题 HDU - 6299

当初好像是随便乱蒙了一个贪心性质就过了 www。

@bzoj - 4922@ [Lydsy1706月赛]Karp-de-Chant Number的更多相关文章

  1. bzoj 4922: [Lydsy1706月赛]Karp-de-Chant Number 贪心+dp

    题意:给定 $n$ 个括号序,让你从中选取一些括号序按照任意顺序拼接,最终生成一个合法的括号序列,求这个合法序列长度最大值. 题解:假设括号序列相对顺序固定,而我们要做的只是判断选还是不选的话可以转化 ...

  2. bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS

    4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 599  Solved: 260[Submit][Stat ...

  3. [BZOJ 4921][Lydsy1706月赛]互质序列

    传送门 因为区间 gcd 的变换不会超过 log 个,所以我们可以暴力枚举区间起点,复杂度是 n*logn 的 #include <bits/stdc++.h> using namespa ...

  4. BZOJ 4919: [Lydsy1706月赛]大根堆 set启发式合并

    这个和 bzoj 5469 几乎是同一道题,但是这里给出另一种做法. 你发现你要求的是一个树上 LIS,而序列上的 LIS 有一个特别神奇的 $O(n\log n) $ 做法. 就是维护一个单调递增的 ...

  5. BZOJ.4919.[Lydsy1706月赛]大根堆(线段树合并/启发式合并)

    题目链接 考虑树退化为链的情况,就是求一个最长(严格)上升子序列. 对于树,不同子树间是互不影响的.仿照序列上的LIS,对每个点x维护一个状态集合,即合并其子节点后的集合,然后用val[x]替换掉第一 ...

  6. [BZOJ 4923][Lydsy1706月赛]K小值查询

    传送门 势能分析平衡树,splay或treap都可以 放个指针版的就跑 #include <bits/stdc++.h> using namespace std; #define rep( ...

  7. BZOJ 4919: [Lydsy1706月赛]大根堆 启发式合并

    我不会告诉你这是线段树合并的好题的... 好吧我们可以搞一个multiset在dfs时求出LIS(自带二分+排序)进行启发式合并,轻松加愉悦... #include<cstdio> #in ...

  8. BZOJ 4919: [Lydsy1706月赛]大根堆

    F[x][i]表示x的子树中取的数字<=i的最大值,线段树合并优化DP 写得很难看,并不知道好看的写法 #include<cstdio> #include<algorithm& ...

  9. BZOJ 4919 [Lydsy1706月赛]大根堆 (SRM08 T3)

    [题解] 求一个序列的LIS有一个二分做法是这样的:f[i]表示长度为i的上升序列中最后一个数最小可以是多少,每次二分大于等于当前数字x的f[j],把f[j]修改为x:如果找不到这样的f[j],那就把 ...

随机推荐

  1. redis异常-MISCONF Redis is configured to save RDB snapshots

     在eclipse中用java代码通过jedis操作redis的时候,报这个错:   redis.clients.jedis.exceptions.JedisDataException: MISCON ...

  2. GIT → 11:Git 工作流与实战演练

    GIT → 11:Git 工作流与实战演练

  3. Docker搭建ELK的javaweb应用日志收集存储分析系统

    1.启动elasticsearch docker run -d --name myes -p 9200:9200 elasticsearch:2.3 2.启动kibana docker run --n ...

  4. git仓库远程连接GitHub

    1 先下载git for windows 然后一直点下一步安装. 2 安装之后,选择git gui.生成ssh 链接 git 公钥. 用命令也可以: $ ssh-keygen -t rsa -C &q ...

  5. SaaS launch Kit成回收宝和友盟云合作纽带,帮助提升3倍上云效率

    导语:叶飞表示,全球二手手机市场未来几年将发生巨大变革, 回收宝正进行积极布局.与阿里云开展紧密技术合作,回收宝期待成为这一变革的引领者. 7月26日,在阿里云上海峰会上,阿里云了发布SaaS生态战略 ...

  6. sublime3安装javascript控制台环境 方法2

    1.下载node.js sublimeText3- 安装nodejs插件   ctrl+shift+p — install package —nodejs 2.修改配置文件 在 Sublie Text ...

  7. ecshop二次开发之单点登录

    单点登录(SingleSignOn),简称为SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 当用户第一次访问应 ...

  8. css中background背景属性概述

    background:url(背景图片路径) no-repeat;/*不重复默认在左上方*/ background:url(背景图片路径) no-repeat center;/*不重复背景图片中间显示 ...

  9. Spring MVC使用ModelAndView进行重定向(转)

    1.Servlet重定向forward与redirect: 使用servlet重定向有两种方式,一种是forward,另一种就是redirect.forward是服务器内部重定向,客户端并不知道服务器 ...

  10. 洛谷P1541 乌龟棋 [2010NOIP提高组]

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...