HDU 6299 B Balanced Sequence 贪心

/**
B Balanced Sequence 
链接: http://acm.hdu.edu.cn/showproblem.php?pid=6299
题意 给你n个只包含‘(‘’和‘)’的字符串;
将这些字符串重新排序连接,问最多有多少个规范的括号(),可以不连续;

思路:贪心,先把规范的去掉,剩下的就是 )  )(  (  连续串的这种形式;
要使得当前的排序对后面的贡献要最大,因此关键在于排序方法;
对于l r 来说  由于需要构造出一种为后面贡献最多的排序
因此l r 的排序方式不过4种;想好正确的贪心策略  是不断的更新r与a[i].l的匹配数

由于是最大的贡献 不妨可以拿出2个子例子进行讨论

a.l   a.r
b.l   b.r

对于最优的情况  那就是 a.l<=a.r&&b.l>b.r  ---->由于窝们的匹配方案是那样的  所以这样来说是最好的方案
对于最坏的情况  那就是 a.l>a.r&&b.l<=b.r  ---->与上诉情况相反

那么还存在两种不确定的情况 可分类讨论一下
可仔细手动模拟一番
a.l<=a.r&&b.l<=b.r  a.l<b.l
a.l>=a.r&&b.l>b.r   a.r>b.r
*/

#include<bits/stdc++.h>
#define ll long long 
using namespace std;

const int maxn=1e5+7;
char str[maxn];

struct node{
	int l,r;
}a[maxn];

stack<char>s;
bool cmp(node a,node b){
    if(a.l<=a.r&&b.l>b.r) return true;
    if(a.l>a.r&&b.l<=b.r) return false;
    if(a.l<=a.r&&b.l<=b.r) return a.l<b.l;   
    if(a.l>=a.r&&b.l>b.r) return a.r>b.r; 
    return true;
}

int main (){
	int t,n,len,ans;scanf("%d",&t);
	while(t--){
		ans=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%s",str);len=strlen(str);
			for(int i=0;i<len;i++){
				if(!s.empty()&&s.top()=='('&&str[i]==')') s.pop(),ans++;
				else s.push(str[i]);
			}
			a[i].l=0,a[i].r=0;
			while(!s.empty()){
				if(s.top()==')') a[i].l++;
				else a[i].r++;
				s.pop();
			} 
		}
		sort(a+1,a+1+n,cmp);
		int ret=0;
		for(int i=2;i<=n;i++){
			ret+=a[i-1].r;
			if(ret>=a[i].l) {
				ans+=a[i].l;
				ret-=a[i].l;//由于是满足匹配的最长没必要连续的序列  因此更新的时候并不需要清零;
			}
			else {
				ans+=ret;
				ret=0;
			}
		}
		printf("%d\n",ans*2);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/81783088