题意:给定 $n$ 个括号序,让你从中选取一些括号序按照任意顺序拼接,最终生成一个合法的括号序列,求这个合法序列长度最大值.

题解:假设括号序列相对顺序固定,而我们要做的只是判断选还是不选的话可以转化为一个简单的背包问题:

令 $f[i][j]$ 表示考虑前 $i$ 个括号序,左括号比右括号多 $j$ 个的最长长度.

转移为:$f[i][j]=max(f[i][j],f[i-1][j-k]+len[i])$ 其中 $k$ 表示当前序列 $i$ 中右括号比左括号多的个数.

转移的时候让 $j>=0$,这样就不会出现不合法的情况了.

但是,我们要给序列设计一个顺序,这也是本题的难点.

但是,可以看出这个和之前一道贪心题挺像的.

初始血量为 $0$,右括号减血,左括号加血,让你设计一种排序方式使得尽可能拿更多的序列.

那么,显然要将能回血的且右括号更小的放到前面,然后对于不能回血的将左括号多的放前面.

#include <bits/stdc++.h>
#define N 310
using namespace std;
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
struct node
{
int x,y,z;
bool operator<(const node a) const
{
if(y>0&&a.y<=0) return 1;
if(y<0&&a.y>=0) return 0;
if(y>0) return x<a.x;
return x+y>a.x+a.y;
}
}a[N];
int f[N][N*N];
char str[N];
int main()
{
// setIO("input");
int n,m=0,i,j;
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%s",str);
a[i].z=strlen(str),m+=a[i].z;
for(j=0;j<a[i].z;++j)
{
a[i].y+=(str[j]=='('?1:-1),a[i].x=max(a[i].x,-a[i].y);
}
}
sort(a+1,a+1+n);
// for(j=0;j<=m;++j) f[0][j]=-1000000000;
memset(f[0],0xc0,sizeof(f[0]));
f[0][0]=0;
for(i=1;i<=n;++i)
{
for(j=0;j<=m;++j) f[i][j]=f[i-1][j];
for(j=a[i].x;j<=m;++j)
if(j+a[i].y>=0&&j+a[i].y<=m)
f[i][j+a[i].y]=max(f[i][j+a[i].y],f[i-1][j]+a[i].z);
}
printf("%d\n",f[n][0]);
return 0;
}

  

bzoj 4922: [Lydsy1706月赛]Karp-de-Chant Number 贪心+dp的更多相关文章

  1. @bzoj - 4922@ [Lydsy1706月赛]Karp-de-Chant Number

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令 ...

  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. PAT(B) 1059 C语言竞赛(C)

    题目链接:1059 C语言竞赛 (20 point(s)) 题目描述 C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛.既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 冠军将赢得一份" ...

  2. 【Leetcode】746. Min Cost Climbing Stairs

    题目地址: https://leetcode.com/problems/min-cost-climbing-stairs/description/ 解题思路: 官方给出的做法是倒着来,其实正着来也可以 ...

  3. SQL高级教程

    一.top子句 top子句用于规定要返回的记录的数目 并非所有数据库系统都支持top子句 # sqlserver SELECT TOP number|percent column_name(s) FR ...

  4. DEFAULT CURRENT_TIMESTAMP

    alter table t_user_channel_info change update_dttm update_dttm timestamp NOT NULL DEFAULT CURRENT_TI ...

  5. java-websocket客户端 断线重连 注入Service问题

    java版客户端: 使用开源项目java-websocket, github地址: https://github.com/TooTallNate/Java-WebSocket github上有很多示例 ...

  6. SQL查看数据库中每张表的数据量和总数据量

    查看所有表对应的数据量 SELECT a.name AS 表名, MAX(b.rows) AS 记录条数 FROM sys.sysobjects AS a INNER JOIN sys.sysinde ...

  7. physdiskwrite 的简单使用

    physdiskwrite 的简单使用 参考  https://m0n0.ch/wall/physdiskwrite.php 来源 https://www.cnblogs.com/EasonJim/p ...

  8. Verilog HDL

    https://wenku.baidu.com/view/9943b7acf524ccbff1218463.html https://hdlbits.01xz.net/wiki/Main_Page h ...

  9. gradle上传jar包到maven公共仓库

    首先这里说的中央仓库 是指的 https://issues.sonatype.org/ 而不是maven私服. 其次是使用gradle上传jar包,maven上传,网上有很多教程,这里不做赘述. 首选 ...

  10. tree 树形加载及增删改

    //异步1<template> <div class="addequipment org"> <div class="top"&g ...