HDU 6299-Balanced Sequence(贪心)

Chiaki has n strings s1,s2,…,sn consisting of '(' and ')'. A string of this type is said to be balanced:
+ if it is the empty string
+ if A and B are balanced, AB is balanced,
+ if A is balanced, (A) is balanced.
Chiaki can reorder the strings and then concatenate them get a new string t . Let f(t) be the length of the longest balanced subsequence (not necessary continuous) of t . Chiaki would like to know the maximum value of f(t) for all possible t .

Input

There are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤105 ) -- the number of strings.
Each of the next n lines contains a string si (1≤|si|≤105 ) consisting of `(' and `)'.
It is guaranteed that the sum of all |si| does not exceeds 5×106 .

Output

For each test case, output an integer denoting the answer.

Sample Input

2

1

)()(()(

2

)(

Sample Output

4

2

题目大意:每个样例给出n个串,n个串能够自由组合,要求输出最大的符合数。例如:)()(()(,有2组(),所以输出4,样例2:2个串组合成)(),有一组(),所以输出2。

思路:不改变串,所以先提取出每个串中原有的符合数,再进行组合,除去后剩余的就只有四种情况,((((全左,))))全右,))(((左大于右,)))((右大于左。相等的情况可以不用考虑。对这4种进行排列获得最大组合数,那就一定是左边多的放在最前面,右边多的放在最后面即可。

注意:重载运算符的条件需要考虑清楚。

......本来我用栈写的结果T无数发,还以为这题卡容器,结果网上有大佬用栈过了......还木有找出问题。

模拟栈ac代码:

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<stdlib.h>
#include<string.h>
//#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i)
#define max(a,b)  a>b?a:b
#define min(a,b)  a<b?a:b
#define LL long long 
#define swap(a,b) {int t=a;a=b;b=t} 
using namespace std;
//using namespace __gnu_cxx;
struct node{
	int x;
	int y;
}p[100005];
int cmp(const node &a,const node &b)
{
	if(a.y>=a.x&&b.y<b.x) return 0;//边界情况 
	if(a.y<a.x&&b.y>=b.x) return 1;//边界情况 
	if(a.y<a.x&&b.y<b.x) return a.y<b.y;
	else return a.x>b.x; 
}//对应4种情况的排列 
int main()
{
	int t,n,k;
	scanf("%d",&t);
	while(t--)
	{
		k=0;
		memset(p,0,sizeof(p));
		string s;
		scanf("%d",&n);
		per(i,0,n-1){
			cin>>s;
			per(j,0,s.size()-1){
				
				if(s[j]==')')
				{
					if(p[i].x<=0) p[i].y++;
					else p[i].x--,k++;
				}
				if(s[j]=='(') p[i].x++;
			}
			
		}
		sort(p,p+n,cmp);
		int l=0;
		per(i,0,n-1){
		     if(p[i].y<=l){
		     	k+=p[i].y;
		     	l-=p[i].y;
			 }else{
			 	k+=l;l=0;
			 }
			 l+=p[i].x;
		}
		cout<<k*2<<endl;
	}
	return 0;
}

自己写的不知道哪儿错的栈代码:(T)

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<stdio.h>
#include<sstream>
#include<stdlib.h>
#include<string.h>
//#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i)
#define max(a,b)  a>b?a:b
#define min(a,b)  a<b?a:b
#define LL long long 
#define swap(a,b) {int t=a;a=b;b=t} 
using namespace std;
//using namespace __gnu_cxx;
struct node{
	int x;
	int y;
}p[100005];
int cmp(const node &a,const node &b)
{
	if(a.y==0) return 1;
	if(b.y==0) return 0;
	if(a.x>=a.y&&b.x<b.y) return 1;
	if(a.x>=a.y&&b.x<b.y) return 0;
	if(a.x>=a.y&&b.x>=b.y) return a.y<=b.y;
	return a.x>=b.x; 
} 
int main()
{
	int t,n,k;
	scanf("%d",&t);
	while(t--)
	{
		k=0;
		memset(p,0,sizeof(p));
		stack<char>q;
		string s;
		scanf("%d",&n);
		per(i,1,n){
			cin>>s;
			per(j,0,s.size()-1){
				if(s[j]=='(') q.push(s[j]);
				if(s[j]==')')
				{
					if(!q.empty()&&q.top()=='(') k++,q.pop();
					else  q.push(s[j]);
				}
			}
			while(!q.empty())
			{
				if(q.top()=='(') p[i].x++;
				else if(q.top()==')') p[i].y++;
				q.pop();
			}
		}
		sort(p+1,p+n+1,cmp);
		int l=0;
		per(i,1,n){
		     if(p[i].y<=l){
		     	k+=p[i].y;
		     	l-=p[i].y;
			 }else{
			 	k+=l;l=0;
			 }
			 l+=p[i].x;
		}
		cout<<k*2<<endl;
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值