0
点赞
收藏
分享

微信扫一扫

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 条评论