hdu6299(贪心)

很好的一题贪心,自己死活想不出来怎么贪,一直去想几种特殊情况,比如(()()) , (()()())之类的,绕进死胡同了,这题关键是把已经匹配好的括号去掉,只考虑剩余部分怎么拼接才能最大化

参考博客

看完这个博客思路后自己实现的时候除了点小问题,就是排序的时候出现死循环了,查了百度后可能原因是有相同的元素返回true导致不断排序,解决办法是让相同元素返回false或者使用stable_sort(),但是我用了之后还是wa了,可能还是排序写残了,博客里的解决办法是先把全都为)或者全都为(的串单独提出来,剩下的再进行排序就好了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
const int mx = 1e5 + 5;
char stack[mx];
char str[mx];

struct node {
    int left, right;
}pt[mx],l[mx],r[mx], mid[mx];

bool cmp(node a, node b) {
    if (a.left >= a. right && b.left >= b.right) return a.right < b.right;
    else if (a.left >= a.right) return true;
    else if (b.left >= b.right) return false;
    else return a.left > b.left;
}

int main() {
    //freopen("1002.in", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int T;
    scanf("%d", &T);

    while (T--) {
        int n, ans = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", str);
            int len = strlen(str);
            int top = 0, cnt = 0;
            pt[i].left = 0; pt[i].right = 0;
            for (int j = 0; j < len; j++) {
                if (str[j] == '(') {
                    pt[i].left++;
                    stack[top++] = '(';
                }
                else  {
                    pt[i].right++;
                    if (top > 0 && stack[top-1] == '(') {top--; cnt++;}
                    else stack[top++] = ')';
                }
            }
            ans += cnt; pt[i].left -= cnt; pt[i].right -= cnt;
            //printf("ans = %d left = %d right = %d\n", ans, pt[i].left, pt[i].right);
        }
        int k1 = 0, k2 = 0, k3 = 0;
        
        for (int i = 1; i <= n; i++) {
        	if (pt[i].left && pt[i].right == 0) l[++k1] = pt[i];
        	else if (pt[i].left == 0 && pt[i].right) r[++k3] = pt[i];
        	else mid[++k2] = pt[i];
		}

        sort(mid+1, mid+1+k2, cmp);
		
        int top = 0;
        
        for (int i = 1; i <= k1; i++) {
        	for (int j = 1; j <= l[i].left; j++)
        		stack[top++] = '(';
		}
        for (int i = 1; i <= k2; i++) {
        	//printf("pt[%d] %d %d\n",i, pt[i].left, pt[i].right);
            for (int j = 1; j <= mid[i].right; j++) {
                if (top > 0 && stack[top-1] == '(') {top--; ans++;}
                else stack[top++] = ')';
            }
            for (int j = 1; j <= mid[i].left; j++)
                stack[top++] = '(';
        }
        for (int i = 1; i <= k3; i++) {
        	for (int j = 1; j <= r[i].right; j++)
        		if (top > 0 && stack[top-1] == '(') {
        			top--; ans++;
				}
		}
        printf("%d\n", ans*2);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值