HDU - 6299 Balanced Sequence (贪心)

题意:给你n个只含'(' ')'的字符串, 你可以将这些字符串左右端随意连接成一个新串,然后求出能得到的符合条件的 最长子序列。
条件:(1) 空串符合 (2) 如果A符合则 (A)也符合 (3)如果A,B符合则 AB也符合 : 总言之就是将这个括号串放入栈中,如果能够全部弹出则为符合条件的串(左右括号匹配就弹出)
思路:关于这道题,一开始可能不会想到贪心。(读题都读到自闭..)但是后面会发现要使子序列最长,我们肯定希望在某个串中最近的两个左右括号匹配
比如  ) ( ( ) ( ( ) ,我们肯定希望2与4匹配而不是与7匹配, 即只要在串中右两个匹配即把它算到最长子序列的串中。

这样以来我们取完这匹配好的括号后就只剩  ) ( (  , 上面样例字符串。即任何一个字符串匹配完最后会出现左右括号剩余(或者没有)的情况

接下来就是讨论像多个串有 ) (  这种形式如何最大匹配。首先按照贪心的想法,我们肯定要让两个串左右两边尽可能接近这样不会浪费括号。

当我们匹配相邻的两个串时,比如 a: )))(  b:)((  ,我们会找左右括号哪边更大:a的右括号数大于左括号,b的左括号数大于右括号,所以大大匹配,这两个就要交换位置

如果 a:)))((   b:))( 两边都是右括号小于左括号,则我们希望两个串左括号或者右括号数目更多的进行匹配。 当然反之同理(就是右括号比左括号多的情况)

所以这样我们就得到了贪心的排序:

 if(a.l > a.r) return b.l > b.r? a.r < b.r : true;
 if(a.l <= a.r) return b.l <= b.r? a.l > b.l :  false;

code:

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int maxn = 1e5+10;
struct node{
    int l,r;
}p[maxn];
bool cmp(node a,node b){
    if(a.l > a.r) return b.l > b.r? a.r < b.r : true;
    if(a.l <= a.r) return b.l <= b.r? a.l > b.l :  false;
}
char s[maxn];
int main(){
    int n;
    int T;
    scanf("%d",&T);
    while(T--){
       scanf("%d",&n);
       int ans = 0;
       for(int i = 1;i <= n;i++){
            scanf("%s",s);
            int len = strlen(s);
            p[i].l = p[i].r = 0;
            for(int j = 0;j < len;j++){
                if(s[j] == '(') p[i].l++;
                else{
                    if(p[i].l > 0){
                        p[i].l--;
                        ans += 1;
                    }
                    else{
                        p[i].r++;
                    }
                }
            }
       }
        sort(p+1,p+n+1,cmp);
        int l=0;
        for(int i=1; i<=n; i++)
        {
            if(p[i].r<=l)
                ans+=p[i].r,l-=p[i].r;
            else ans+=l,l=0;
            l += p[i].l;
        }
        printf("%d\n",ans*2);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Tianwell/p/11356784.html