BZOJ4922 Karp-de-Chant Number

84 篇文章 1 订阅
22 篇文章 0 订阅

这题真是tmd……让我想起了做bohater时候的绝望

还好最后A了

注意到每个括号序列相当于必须在当前前缀和>=x的情况下才能选,选完之后前缀和会+y

那么就是bohater原题了,按那道题的顺序排序一下,然后DP即可,f[i][j]表示只用前i个串前缀和为0的最长长度

答案为f[n][0]

#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 310
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct data{
	int x;
	int y;
	int len;
};
int n;
char s[MAXN];
int f[MAXN][MAXN*MAXN];
data a[MAXN];
data b[MAXN];
int tot1,tot2;
int ans;
bool cmp1(const data &x,const data &y){
	return x.x<y.x;
}
bool cmp2(const data &x,const data &y){
	return x.x+x.y>y.x+y.y;
}
int main(){
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%s",s+1);
		a[i].x=0;
		int now=0;
		for(j=1;s[j];j++){
			now+=s[j]=='('?1:-1;
			a[i].x=max(a[i].x,-now);
		}
		a[i].len=j-1;
		a[i].y=now;
	}
	for(i=1;i<=n;i++){
		if(a[i].y>=0){
			a[++tot1]=a[i];
		}else{
			b[++tot2]=a[i];
		}
	}
	if(tot1){
		sort(a+1,a+tot1+1,cmp1);
	}
	if(tot2){
		sort(b+1,b+tot2+1,cmp2);
	}
	memset(f,0xef,sizeof(f));
	f[0][0]=0;
	for(i=1;i<=tot2;i++){
		a[tot1+i]=b[i];
	}
	int s=0;
	for(i=1;i<=n;i++){
		for(j=0;j<=s;j++){
			f[i][j]=f[i-1][j];
		}
		for(j=a[i].x;j<=s;j++){
			f[i][j+a[i].y]=max(f[i][j+a[i].y],f[i-1][j]+a[i].len);
		}
		s+=a[i].len;
	}
	printf("%d\n",f[n][0]);
	return 0;
}

/*

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值