AtCoder Beginner Contest 167 F:Bracket Sequencing 貪心分析

首先我們知道,判一個字符串是否合法,肯定是判任意前綴 ( 的個數一定大於等於 ) 的個數

而多個字符串考慮什麼樣的字符串放在最左邊比較好。

對於一個字符串對拼接有影響的括號一定是自己內部匹配後剩的括號,比如  )(()(  內部匹配一對,剩2個左括號,一個右括號。

顯然字符串內部括號匹配完後,剩的都是“(”,且剩的左括號的最多,這樣的字符串放在最左邊。比如()()((  剩2個左括號

同理,最右邊一定是,剩的右括號最多的字符串。

依照最左最右,我們往中間放。

首先左括號剩的多的肯定儘量放左邊,右括號剩的多的儘量放右邊。

然後考慮次左應該放什麼最優。

先把左括號剩的多的在左邊安排好:

由於最左邊有剩餘的左括號,我們每放一個  存在剩右括號  的字符串,都會消耗一部分左括號,我們肯定是讓消耗少的優先放前面。(每次都會補充多餘消耗的左括號,所以左括號會一直變大,而每次選擇消耗最少的,顯然更優)

把左邊的安排完後,右邊同理:

一定是從右往左是:優先讓消耗右括號少的放在最右邊。

綜上:對於每個字符串 剩下的左括號a,剩下的右括號b。

如果a>=b 其放到左邊。

否則  都放在右邊

對於左邊的字符串,b越小,越在左邊

對於右邊的字符串,a越小,越在右邊

然後就可以用結構體排序搞一搞了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/

char s[M];
struct na{
	int x,y;
	bool operator <(const na &r)const
	{
		return y<r.y;
	}
};
struct nb{
	int x,y;
	bool operator <(const nb &r)const
	{
		return x>r.x;
	}
};
vector<na>va;
vector<nb>vb;
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
  	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		int l=strlen(s);
		int a=0,b=0;
		for(int j=0;j<l;j++)
		{
			if(s[j]=='(')a++;
			else
			{
				if(a)a--;
				else b++;
			}
		}
		//這裏a的意思是需要在這個字符串後面補多少右括號,b是需要在其前面補多少左括號 
	 	//當a>b時,說明做左括號比右括號多,肯定優先放前面。顯然,此時b越小在前面越優,因爲需要在前面補左括號的個數就少了 
		//a<b時同理
	//	cout<<a<<" "<<b<<endl;
		if(a>=b)va.pb(na{a,b});
		else vb.pb(nb{a,b});
	} 
	sort(va.begin(),va.end());
	sort(vb.begin(),vb.end());
	bool f=true;
	int sm=0;
	for(int i=0;i<va.size();i++)
	{
		sm-=va[i].y;
		if(sm<0)f=false;//前面的左括號能否滿足當前字符串的需要
		sm+=va[i].x;//當前字符串所能提供的左括號
		//肯定是左括號需求量少的在前面 
	}
	for(int i=0;i<vb.size();i++)
	{
		sm-=vb[i].y;
		if(sm<0)f=false;
		sm+=vb[i].x;
		//右邊肯定是對稱的來考慮,即需求後面右括號少的放在最右邊 
	}
	if(sm!=0)f=false;
	if(f)cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章