Ⅰ . 贪 心 , 神 仙 思 维 \color{Red}Ⅰ.贪心,神仙思维 Ⅰ.贪心,神仙思维
设 置 一 个 变 量 k 遇 到 ( 加 一 , 遇 到 右 括 号 减 去 一 设置一个变量k遇到(加一,遇到右括号减去一 设置一个变量k遇到(加一,遇到右括号减去一
遇 到 问 号 就 暂 时 把 问 号 当 成 右 括 号 遇到问号就暂时把问号当成右括号 遇到问号就暂时把问号当成右括号
为 什 么 暂 时 当 成 右 括 号 ? 因 为 当 成 右 括 号 的 话 为什么暂时当成右括号?因为当成右括号的话 为什么暂时当成右括号?因为当成右括号的话
后 续 如 果 想 把 这 个 问 号 换 成 左 括 号 的 话 仍 然 是 合 法 的 后续如果想把这个问号换成左括号的话仍然是合法的 后续如果想把这个问号换成左括号的话仍然是合法的
如 果 暂 时 当 成 左 括 号 , 可 能 后 续 换 成 右 括 号 的 时 候 有 些 问 号 就 不 能 换 如果暂时当成左括号,可能后续换成右括号的时候有些问号就不能换 如果暂时当成左括号,可能后续换成右括号的时候有些问号就不能换
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
cin >> s;
int len = s.length(),ans=0;
for(int i=0;i<len;i++)
{
int k=0,r=0;
for(int j=i;j<len;j++)
{
if(s[j]=='(') k++;
else if(s[j]==')') k--;
else k--,r++;//暂时变成右括号
if(!k) ans++;
if(k<0)
{
if(!r) break;
else k+=2,r--;//把之前的右括号变成左括号
}
}
}
cout<<ans;
}
Ⅱ . 结 论 法 , 不 会 证 明 \color{Red}Ⅱ.结论法,不会证明 Ⅱ.结论法,不会证明
假 如 没 有 问 号 限 制 , 设 字 符 串 s 长 n , 合 法 的 条 件 是 假如没有问号限制,设字符串s长n,合法的条件是 假如没有问号限制,设字符串s长n,合法的条件是
对 于 任 意 的 i ∈ [ 1 , n ] 对于任意的i\in[1,n] 对于任意的i∈[1,n]
[ 1 , i ] 中 ( 的 数 量 大 于 ) 的 数 量 [1,i]中(的数量大于)的数量 [1,i]中(的数量大于)的数量
[ i , n ] 中 ) 的 数 量 大 于 ( 的 数 量 [i,n]中)的数量大于(的数量 [i,n]中)的数量大于(的数量
s 串 中 ( 和 ) 数 量 相 同 s串中(和)数量相同 s串中(和)数量相同
上面的推论显然正确,因为我们已经排除了所以不合法的情况
现 在 加 入 了 ? , 其 实 换 汤 不 换 药 现在加入了?,其实换汤不换药 现在加入了?,其实换汤不换药
对 于 任 意 的 i ∈ [ 1 , n ] 对于任意的i\in[1,n] 对于任意的i∈[1,n]
[ 1 , i ] 中 ( 的 数 量 + ? 的 数 量 大 于 ) 的 数 量 [1,i]中(的数量+?的数量大于)的数量 [1,i]中(的数量+?的数量大于)的数量
[ i , n ] 中 ) 的 数 量 + ? 的 数 量 大 于 ( 的 数 量 [i,n]中)的数量+?的数量大于(的数量 [i,n]中)的数量+?的数量大于(的数量
#include <bits/stdc++.h>
using namespace std;
const int maxn=5005;
string s;
int n,ans,ok[maxn][maxn];
int main()
{
cin >> s;
int n = s.length();
for(int i=0;i<n;i++)
{
int l = 0,r = 0,q = 0;
for(int j=i;j<n;j++)
{
if(s[j] == '(') l++;
else if(s[j] == ')') r++;
else q++;
if(l+q<r) break;//再往后都不可能了
ok[i][j]=1;
}
}
for(int i=n-1;i>=0;i--)
{
int l=0,r=0,q=0;
for(int j=i;j>=0;j--)
{
if(s[j] == '(') l++;
else if(s[j] == ')') r++;
else q++;
if(r+q<l) break;
if(ok[j][i] && (i-j) % 2 == 1) ans++;
}
}
cout<<ans;
}