2018 Multi-University Training Contest 1-1002 -Balanced Sequence(括号匹配+贪心)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6299

题目:

题意:t组数据,每组数据给你一个n表示给你n个括号串,这n个括号串之间进行组合,求能够匹配的长度。

思路:用一个结构体来记录每个字符串的左括号和右括号的数量,在输入时将同串中能够匹配的直接消掉,最后剩余的字符绝对是所有的右括号在左边,左括号在右边,假设当前字符串为())(()(,我们一次将其标记为1~7,那么1和2可以匹配,5可以和6匹配,最后剩余347,也就是)((。我们紧接着就对n个形如刚刚例子中的347这样的括号进行贪心,排序即可(排序分析见代码注释)。

代码实现如下:

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <stack>
 5 #include <cmath>
 6 #include <bitset>
 7 #include <cstdio>
 8 #include <string>
 9 #include <vector>
10 #include <cstdlib>
11 #include <cstring>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 typedef long long ll;
17 typedef unsigned long long ull;
18 
19 #define bug printf("*********\n");
20 #define FIN freopen("D://code//in.txt", "r", stdin);
21 #define debug(x) cout<<"["<<x<<"]" <<endl;
22 #define IO ios::sync_with_stdio(false),cin.tie(0);
23 
24 const double eps = 1e-8;
25 const int mod = 1e9 + 7;
26 const int maxn = 1e5 + 7;
27 const double pi = acos(-1);
28 const int inf = 0x3f3f3f3f;
29 const ll INF = 0x3f3f3f3f3f3f3f3f;
30 
31 inline int read() {//读入挂
32     int ret = 0, c, f = 1;
33     for(c = getchar(); !(isdigit(c) || c == '-'); c = getchar());
34     if(c == '-') f = -1, c = getchar();
35     for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
36     if(f < 0) ret = -ret;
37     return ret;
38 }
39 
40 
41 int t, n, ans;
42 string s;
43 
44 struct node {
45     int p, q; //p为左括号数,q为右括号数,看那个半圆朝向是不是非常生动形象~
46     bool operator < (const node& x) const {//排序只需比较两个即可,
47         //因为相互之间比较都是一对一,所以在此处将所有可能的情况列举出来即可;
48         if(q >= p && x.q < x.p) return false; //当前的左括号数小于等于右括号数,x的右括号数小于左括号数,那么要想匹配的更多
49         //肯定是x排在前面;
50         if(q < p && x.q >= x.p) return true; //与上面情况刚好相反;
51         if(q >= p && x.q >= x.p) return p > x.p;//都是右括号数大于等于左括号数,那么就想象是最后两个进行比较,为了能够匹配更多
52         //那么最后一个的左括号数一定要最少,前面的同理;
53         return q < x.q; //情况与上述相反,可以想象是第一个和第二个比较。
54     }
55 }a[maxn];
56 
57 int main() {
58     IO;
59     //FIN;
60     cin >>t;
61     while(t--) {
62         cin >>n;
63         ans = 0;
64         for(int i = 0; i < n; i++) {
65             cin >>s;
66             a[i].p = a[i].q = 0;
67             for(int j = 0; j < s.size(); j++) {
68                 if(s[j] == '(') a[i].p++; //将所有的左括号记录下来;
69                 if(s[j] == ')') {
70                     if(a[i].p > 0) { //当前右括号前面还有左括号没有匹配,那么不记录当前的右括号,
71                         //并将前面的左括号数减一,相当于匹配了一对括号;
72                         a[i].p--;
73                         ans += 2;
74                     }
75                     else a[i].q++; //否则就记录右括号
76                 }
77             }
78         }
79         sort(a, a + n);
80         int nw = 0; //记录前面还有多少个左括号没有匹配,因为括号匹配间没要求是连续的,所以当前的右括号可以匹配上上个括号
81         for(int i = 0; i < n; i++) {
82             if(a[i].q > nw) a[i].q = nw;
83             ans += a[i].q * 2;
84             nw -= a[i].q;
85             nw += a[i].p;
86         }
87         cout <<ans <<"\n";
88     }
89     return 0;
90 }

 

posted @ 2018-07-23 23:18  Dillonh  阅读(558)  评论(0编辑  收藏  举报