题解:CF917A The Monster
CF917A 题解
题面
思路
看了下题目,很简单,直接从开头开始爆搜即可,枚举出一种可能,答案就加一。
问题来了,爆搜的过程呢?
容易想到,可以用一个变量 sum 动态统计当前序列未配对的左括号的数量,对于一个 s[i](i∈[1,strlen(s)]) 有如下两种情况:
- 若 s[i] 为
(
,则 sum 加一,表示未配对的左括号数加一。 - 若 s[i] 为
)
,则 sum 减一,表示未配对的左括号数减一。
如上是正常情况,接下来要考虑特殊情况:如果 s[i] 是 ?
呢?容易想到,再用一个 num 来统计 ?
修改成 )
的个数,接下来同样的,分成两种情况,讨论 ?
是换成 (
还是 )
:
- 若未配对的左括号的数量大于 0,即 sum>0 时,则把
?
变成)
去和左括号配对。所以是 sum−1,num+1。 - 否则,
?
变成(
,即 sum+1。
于是,一个子区间就处理好了,接下来要对这个子区间进行判断,有如下三种情况:
- sum<0,num>0,说明可以把之前的右括号改为左括号,则 sum+2,并且 num−1。
- sum<0,num=0,则序列违法,无法每对括号都匹配成功。
- sum=0,则这个序列满足条件,ans+1。
于是,代码基本就可以出来了。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
char s[5005];
int sum,ans,num,len;
//sum是用来记录未配对的左括号的数量。
//ans为答案。
//num统计‘?’可以修改成‘)’的个数。
//len来统计输入序列的长度。
int main(){
cin>>s;
len=strlen(s);//求输入的字符串的长度。
for(int i=0; i<len; i++){//暴力枚举。
sum=0,num=0;//初始化。
for(int j=i; j<len; ++j){
if(s[j]=='(') sum++;//正常情况:为前括号,未配对的左括号数+1。
if(s[j]==')') sum--;//正常情况:未配对的左括号数-1。
if(s[j]=='?'){//特殊情况‘?’,可以为任意符号。
if(sum>0) sum--,num++;
else sum++;
}
if(sum<0&&num) sum+=2,num--;//sum<0且num>0,说明可以把之前的右括号改为左括号,则sum+=2,并num--;。
if(sum<0&&!num) break;//序列违法,无法每对括号配对成功。
if(sum==0) ans++;//sum等于0则答案就多一种,ans++;。
}
}
cout<<ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现