AtCoder Beginner Contest 167 F - Bracket Sequencing(贪心+排序)

链接

题意:

给出\(N\)个字符串,全都是由()组成的,判断\(S_1,S_2.....S_n\)能否以合理的顺序,满足其中的()配对成功。(注意配对的()一定是(在前,)在后).

思路:

首先这是个字符串匹配问题,我们就可以将其转化成(为1,)为-1.这样就将一个字符串转化两个有意义的值,一个是最小前缀值(就是前面有多少个没有匹配的))我们用MinNum来表示,还有一个就是字符串的值(也就是整个字符串需要多少个其他(,或者)来中和)我们用Num来表示.举个例子( ( ) ) ) ) (( ,MinNum = -2 Num = 0.

显然我们从头分配字符串的话不能有前缀小于0,如果有就说明前面有)没有匹配,就一定不符合条件.并且最后所有字符串都放上之后,最终的值一定是0,不然就说明还有(没有中和掉.

假设TotalNum是遍历到字符串\(S_i\)之前的数字和,那么要求TotalNum+MinNum >= 0,满足条件就更新TotalNum,新的TotalNum=TotalNum+Num

那么如何排序字符串\(S_i\),保证尽可能满足这个条件呢?

显然可以按照minNum从大到小进行排列(totalNum>0),但是totalNum >0和totalNum < 0 显然是两种情况,应该分开来讨论,所以说设置两个数组v1,v2一个用来存储totalNum>0,一个用来存储totalNum < 0,那么最终两个数组v1和v2的TotalNum应该互为相反数。

这里我说下\(v_2\)为什么加进去的是 v2.push_back({minNum-num,-num});//都转化成反方向
其实就是想到与转成反方向,例如(()))()))((MinNum=-3,Num=-1;
他就相当于))((()((()) MinNum= -2 Num=1;
这个地方就是不好理解.

vector<pii> v1;
vector<pii> v2;
void solve()
{
	ll n;
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		string str;
		cin>>str;
		ll minNum=1e9+7,num=0;
		for(int j=0;j<str.size();j++){
			if(str[j]=='('){
				num++;
			}else {
				num--;
			}
			minNum=min(minNum,num);
		}
		if(num>0) v1.push_back({minNum,num});
		else v2.push_back({minNum-num,-num});//都转化成反方向
	}
    sort(v1.begin(),v1.end());
    sort(v2.begin(),v2.end());
    reverse(v1.begin(),v1.end());
    reverse(v2.begin(),v2.end());
	
	ll now=0;
	for(int i=0;i<v1.size();++i){
		if(now+v1[i].x<0){
			puts("No");			
			return ;
		}
		now=now+v1[i].y;
	}
	
	ll now1=0;
	for(int i=0;i<v2.size();i++){
		if(now1+v2[i].x<0){
			puts("No");
			return ;
		}
		now1=now1+v2[i].y;
	}
	
	if(now!=now1) {
		puts("No");
		return ;
	}
	puts("Yes");	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值