HDU 6299 Balanced Sequence 2018多校第一场

Problem Description

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

 

 

题意:首先给出一个n, 之后给出n个只包含(或)的字符串, 然后让你把这n个串拼起来, 使得最终形成的串的平衡子串最长, 平衡子串的定义:1、()这是一个平衡子串  2、(A), 其中A是平衡子串 3、 空串是平衡子串; 最终输出平衡子串的长度

 

思路:这个题的思路很屌, 首先这是一个贪心的思路, 不是dp的思路, 怎么贪呢?  首先考虑每一个串, 对于这个串里本身的平衡子串, 我们可以用栈直接统计出来, 之后剩下的串要么是只含有(, 要么只含有), 要么是)(的连续串。 之后我们考虑通过排序将这n个处理之后的串连起来, 致使最后的串的平衡长度最长。 排序规则: 排在前面的要尽量为后面做贡献, 所以我们首先考虑(个数大于)个数的串, 将这些串排在前面, 这样我们就可以使得前面的串可以尽量的为后面做贡献(实在想不明白的话可以自己画两个例子实现一下就会发现了), 之后对于(个数大于)个数的串和(个数小于)个数的串之间的排序, 我们可以比较一下两个串哪一个在前面产生的收益高, 我们就让哪个串排在前面;

 

具体代码:

#include 
#include 
#include 
#include 
#include 

const int maxed = 100000 + 10;

struct Node
{
    int x, y;
    bool operator < (const Node& n1) const
    {
        if (x >= y && n1.x < n1.y)
            return true;
        if (x < y && n1.x >= n1.y)
            return false;
        int val = std::min(x, n1.y), val_1 = std::min(n1.x, y);
        return val > val_1;
    }
}node[maxed];

std::stack sta;
int n;

int main()
{
    int N;
    scanf("%d", &N);
    while (N--) {
        while (!sta.empty())
            sta.pop();
        scanf("%d", &n);
        getchar();
        char c;
        int answer = 0, cnt = 0;
        for (int i = 1; i <= n; ++i) {
            while (true) {
                c = getchar();
                if (c == '\n')
                    break;
                if (c == '(')
                    sta.push(c);
                else if (sta.empty() || sta.top() == ')')
                    sta.push(c);
                else {
                    answer += 2;
                    sta.pop();
                }
            }
            if (!sta.empty()) {
                cnt += 1;
                node[cnt].x = node[cnt].y = 0;
                while (!sta.empty()) {
                    if (sta.top() == '(')
                        node[cnt].x += 1;
                    else
                        node[cnt].y += 1;
                    sta.pop();
                }
            }
        }
        std::sort(node + 1, node + 1 + cnt);
        for (int i = 1; i <= cnt; ++i) {
            for (int j = 1; j <= node[i].y; ++j) {
                if (!sta.empty() && sta.top() == '(') {
                    sta.pop();
                    answer += 2;
                }
                else
                    sta.push(')');
            }
            for (int j = 1; j <= node[i].x; ++j)
                sta.push('(');
        }
        printf("%d\n", answer);
    }
    return 0;
}

 

感想:多校的第一场。。。体验挺差的。。很难受。。这个题一上来的反应就是dp。。可能是之前的括号匹配都是dp所以直接就惯性思维了。。。这也反映了在做题中只是生搬硬套的一个现象。需要改进。。。也希望以此多校第一场作为暑假的开始, 为之后在下学期的区域赛上能有一个好的表现吧。

你可能感兴趣的:(2018杭电多校)