HDU 6299 Balanced Sequence [贪心]

题意

给你n个包含’(‘与’)’的字符串,可以将这些字符串任意排序,求所有排序中,子序列是正规括号序列的最大长度。

题解

首先我们对所有的字符串找到通过stack找到所有的串内正规括号子序列,之后剩下的串只有三种可能:
1. 只包含’(’
2. 先是一串’)’然后再是一串’(’
3. 只包含’)’
然后,按照第一类,第二类,第三类的顺序放置串。对于第二类内的排序,首先按照’(‘个数贡献正负排序,’)’个数小于’(‘个数则贡献为正,贡献是正的则排前面。然后正贡献的串,我们按照’)’个数从小到大排。负贡献的串,我们按照’(‘个数从大到小排。对于排序完的串,我们从前往后模拟记录一下即可。

AC代码

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
const int MAXN=(int)1e5+10;
struct node
{
    int a,b;
}p[MAXN];
char str[MAXN];
stack<char>s;
vector<node>v1,v2,v3;
bool cmp(node x,node y){
    if(x.a+x.b>=0&&y.a+y.b>=0)return x.a>y.a;
    else if(x.a+x.b>=0)return 1;
    else if(y.a+y.b>=0)return 0;
    else return x.b>y.b;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        while(!s.empty())s.pop();
        v1.clear();v2.clear();v3.clear();
        int step=0,n,ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            for(int j=0;str[j]!='\0';j++)
            {
                if(str[j]=='(')s.push(str[j]);
                else 
                {
                    if(!s.empty()&&s.top()=='(')s.pop(),ans++;
                    else s.push(str[j]);
                }
            }
            int a=0,b=0;    
            while(!s.empty())
            {
                if(s.top()=='(')b++;
                else a--;
                s.pop();
            }
            p[i].a=a;p[i].b=b;
            if(a==0&&b)v1.push_back(p[i]);
            else if(a&&b==0)v3.push_back(p[i]);
            else v2.push_back(p[i]);
        }
        for(int i=0;i<v1.size();i++)
            step+=v1[i].b;
        sort(v2.begin(),v2.end(),cmp);
        for(int i=0;i<v2.size();i++)
        {
            if(step<0)step=0;
            ans+=min(-v2[i].a,step);
            if(step+v2[i].a<0)
            {
                step=v2[i].b;
                continue;
            }
            step+=v2[i].a+v2[i].b;
        }
        for(int i=0;i<v3.size();i++)
        {
            if(step<0)step=0;
            ans+=min(step,-v3[i].a);
            if(step+v3[i].a<0)
            {
                step=0;
                break;
            }
            step+=v3[i].a;
        }
        printf("%d\n",ans*2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acterminate/article/details/81171799