hdu 6299 Balanced Sequence(模拟栈, 贪心)

本文介绍了一种通过优化括号匹配来解决最长平衡子序列问题的方法。重点在于利用结构体记录括号状态,通过排序和模拟操作提高匹配效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Chiaki has n strings s1,s2,…,sn consisting of ‘(’ and ‘)’. A string of this type is said to be balanced:

  • if it is the empty string
  • if A and B are balanced, AB is balanced,
  • if A is balanced, (A) is balanced.

Chiaki can reorder the strings and then concatenate them get a new string t. Let f(t) be the length of the longest balanced subsequence (not necessary continuous) of t. Chiaki would like to know the maximum value of f(t) for all possible t
.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤105) – the number of strings.
Each of the next n lines contains a string si (1≤|si|≤105) consisting of (' and)’.
It is guaranteed that the sum of all |si| does not exceeds 5×106
.
Output
For each test case, output an integer denoting the answer.
Sample Input

2
1
)()(()(
2
)
)(

Sample Output

4
2

题意想必大家都理解,我就不多说了,,,

题的关键在于当左右括号匹配时,将已匹配的括号从数组中删除,并且数量+2(看到这,是不是觉得和栈很像~),最后将每个字符串剩余部分进行组合,达到匹配的括号最大化就可,比赛时我就卡在了这,主要是时间不多了,最后40分钟才开始看,,,

本来开始时我是直接用的栈,但我开始时没想到如何建立栈组,,,不知怎么标记该栈左右剩余的个数及情况,,,emmm后来发现自己想多了,,,其实很简单,只需再开一个数组,建立一个结构体,记录一下左右括号数就行,,,

主要是因为建立结构体后,我就否定了上面的栈, 感觉重新模拟似乎更方便,就干脆直接都是模拟了

不过有一个地方我觉得我没问题,但就是wa,我也不知为何,,,十分难受,,,wa的代码在本篇的最后,有哪位好心的大佬能帮帮我这个小渣渣嘛~

#include<cstdio>
#include<stack>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

#define clr(x) memset(x, 0, sizeof(x));
const int N = 1000010;
typedef long long ll;

struct node{
    int l, r, s;//分别代表左括号,右括号及该字符串最长平衡子串的长度
}a[N], b;

bool cmp(node x, node y){
    if(x.l > x.r && y.r >= y.l)   return 1;
    else if(x.l <= x.r && y.r < y.l)    return 0;
    else if(x.l > x.r && y.l > y.r)     return x.r < y.r;
    else return x.l > y.l;

}

int main(){
    int t, n;
    char c[N];
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        for(int i=0; i<n; i++){
            scanf("%s", c);
            //cout << i << ' ' <<c[i] << endl;
            int len = strlen(c);
            a[i].l = a[i].r = a[i].s = 0;
            for(int j = 0; j < len; j++){
                if(c[j] == '('){
                    a[i].l++;
                }
                else{
                    if(a[i].l > 0){
                        a[i].s += 2;
                        a[i].l--;
                    }
                    else{
                        a[i].r++;
                    }
                }
            }
            //cout << "a " << i << ' ' <<a.top() << endl;
        }
        sort(a, a+n, cmp);
        int l = 0, sum = 0;
        for(int i = 0; i < n; i++){
            sum += a[i].s;
            int r = a[i].r;
            if(l && r){
                int m = min(l, r);
                sum += 2*m;
                l-=m;
            }
            l += a[i].l;
        }
        printf("%d\n", sum);
    }
    //system("pause");
    return 0;
}

哪位大佬能帮忙解释一下 我这个判断为什么不对~哇~难受~qwq

 b.s = b.l = b.r = 0;
 for(int i = 0; i < n; i++){
    b.s += a[i].s;
           b.l += a[i].l;
    b.r += a[i].r;
}
 b.l -= a[n-1].l;
 b.r -= a[0].r;
// cout << b.l << ' ' << b.r << endl;
int m = min(b.l, b.r);
// cout << m << endl;
b.s += 2*m;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值