hdu6299 Balanced Sequence

HDU6299

贪心思想
多组输入,给你多个字符串,字符串间可以任意自由组合,求你取得能够得到最多的()的数量,
首先看到左右括号的配对,想到栈,或者用数组来简化字符串,即到最后字符串有三种形式。
1.只有’(’。
2.只有’)’。
3.既有’)’,也有’(’,组合即为类似‘)))(((’这样的字符串。
空串不予考虑。
第一,第二种的情况都好考虑,第三种相对来说要更加复杂。
对于第一种把其字符串全部放在开头,对于第二种,把其字符串全部放在结尾。
对于第三种分两种情况,贪心的思想
1)如果左括号‘(’多于右括号‘)’,那么按照右括号’)‘从小到大排序。
2)如果左括号’(‘少于右括号’(‘,那么按照左括号’(‘从大到小排序。
上代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 100010
const int mod = 1e9+7;
struct node{
    int l, r;   //分别代表左括号的数量和右括号的数量
    bool operator < (const node b){
        if(l>=r&&b.l>=b.r) return r<b.r;    //如果左括号大于右括号,按照右括号从小到大排序
        else if(l>=r&&b.l<b.r) return 1;    //位置不变
        else if(l<r&&b.l>=b.r) return 0;    //位置交换
        else return l>b.l;                  //如果左括号小于右括号,按照左括号从大到小排序
    }
};
char str[maxn];
int main(){
    ios::sync_with_stdio(0);    //cin优化
    int k;
    scanf("%d", &k);
    while(k--){
        int n;
        scanf("%d", &n);
        int ans = 0;            //记录左右括号匹配的对数,所以到后面要乘2
        vector<node> v;         //这个v是用来存储既有左括号又有右括号的字符串,这种方式大大降低了运行时间
                                //如果是用来存储全部的字符串的话,运行时间在900ms多,但用这种只用了100ms多
        int suml = 0, sumr = 0;     //记录总共的只有左括号和只有右括号的字符串的数量
        for(int i = 0; i < n; i++){
            int l = 0, r = 0;
            scanf("%s", str);
            for(int j = 0; j < strlen(str); j++){
                if(str[j]==')'&&l!=0) l--, ans++;   //只有一种情况是ans要加一的
                else if(str[j] == ')') r++;
                else if(str[j] == '(') l++;
            }
            if(l==0&&r!=0) sumr+=r;     //只有右括号
            else if(l!=0&&r==0) suml+=l;    //只有左括号
            else if(l!=0&&r!=0) v.push_back(node{l, r});    //既有左括号又有右括号
        }
        sort(v.begin(), v.end());   //对v排序
        int tmp = suml;     //tmp表示当前拥有的左括号的数量
        for(int i = 0; i < v.size(); i++){
            if(tmp >= v[i].r){      //如果tmp大于等于v[i].r,即表示可以完全配对该字符串的右括号
                ans += v[i].r;
                tmp += v[i].l;
                tmp -= v[i].r;
            }else {                 //否则表示最多只能配对tmp对左右括号,然后对tmp进行重置
                ans += tmp;
                tmp = v[i].l;
            }
        }
        ans += min(sumr, tmp);  //加上最后的右括号
        printf("%d\n", ans*2);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值