题目链接:哆啦A梦传送门
题意:任意连接n串字符串,使得括号匹配数最大。
题解:模拟,首先预处理每串字符串,使得最后都为 "))(((",")))" , "((",刚开始自己想着不用怎么排序,发现不行,最后看了下题解,加了个排序就行了。
参考链接:https://www.cnblogs.com/Dillonh/p/9357541.html
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
const int maxn=100010;
char op[maxn];
struct node{
int x,y;
}ans[maxn];
bool cmp(node a,node b)
{
if(a.x<=a.y&&b.x>b.y) return 1;///假设当前的左括号数小于等于右括号数,x的右括号数小于左括号数,那么要想匹配的更多
///肯定是x排在前面;
if(a.x>a.y&&b.x<=b.y) return 0; ///与上面情况刚好相反;
if(a.x<=a.y&&b.x<=b.y) return a.x<b.x;///都是右括号数大于等于左括号数,那么就想象是最后两个进行比较,为了能够匹配更多
///那么最后一个的左括号数一定要最少,前面的同理;
if(a.x>=a.y&&b.x>=b.y) return a.y>b.y; ///情况与上述相反
}
char sta[maxn];
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--){
int n;
scanf("%d",&n);
int sum=0,num;
for(int i=1;i<=n;i++){
scanf("%s",op);
// printf("%s\n",op);
int len=strlen(op);
int top=0;
num=0;
for(int j=0;j<len;j++) ///预处理
{
if(op[j]=='(') sta[++top]=op[j];
else if(op[j]==')'&&sta[top]=='('&&top>0){
num+=2;
top--;
}
}
sum+=num;
ans[i].y=top;
ans[i].x=len-num-ans[i].y;
}
sort(ans+1,ans+1+n,cmp);
num=0;
for(int i=2;i<=n;i++)
{
num+=ans[i-1].y;
if(ans[i].x>num){
sum+=num*2;
num=0;
}
else{
sum+=ans[i].x*2;
num-=ans[i].x;
}
}
printf("%d\n",sum);
}
}
/*
))(((
)))((
)((
())
()())(()
))(((
)))((
)((
())
))(()((
)((((((
)))))(
(
)
)(
()
*/
我的标签:做个有情怀的程序员。