题解:CF917A The Monster

CF917A 题解

题面

原题传送门

思路

看了下题目,很简单,直接从开头开始爆搜即可,枚举出一种可能,答案就加一。

问题来了,爆搜的过程呢?

容易想到,可以用一个变量 sum 动态统计当前序列未配对的左括号的数量,对于一个 s[i](i[1,strlen(s)]) 有如下两种情况:

  1. s[i](,则 sum 加一,表示未配对的左括号数加一。
  2. s[i]),则 sum 减一,表示未配对的左括号数减一。

如上是正常情况,接下来要考虑特殊情况:如果 s[i]? 呢?容易想到,再用一个 num 来统计 ? 修改成 ) 的个数,接下来同样的,分成两种情况,讨论 ? 是换成 ( 还是 )

  1. 若未配对的左括号的数量大于 0,即 sum>0 时,则把 ? 变成 ) 去和左括号配对。所以是 sum1,num+1
  2. 否则,? 变成 (,即 sum+1

于是,一个子区间就处理好了,接下来要对这个子区间进行判断,有如下三种情况:

  1. sum<0,num>0,说明可以把之前的右括号改为左括号,则 sum+2,并且 num1
  2. sum<0,num=0,则序列违法,无法每对括号都匹配成功。
  3. 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;
}
posted @   naroto2022  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
花开如火,也如寂寞。