题意:
原先的一个常规的算术表达式中的一些位置的 ( 或者 ) 被 ? 替代了,题目给出一个有字符串,要求将 ? 补全, 如果 ? 的补全方法只有一种输出 YES, 否则输出 NO
思路:
先把首尾去掉,首尾的字符是可以确定的
看中间的问号数量,如果是0或者1,直接输出 YES
因为要使常规的表达式,左括号和右括号的数量必然是 n / 2, n / 2, 记录原先括号里面已经有的就可以知道还需要几个 ( 和 ),
如果只需要一种类型的,直接输出 YES
观察发现最好的情况是先把 ( 全用完, 这里有一种贪心思想,)越往后能构成的几率肯定是越大的,所以上述情况是最优解,
次优解就是把 上述情况第一个 问号变 )的位置和前一个进行交换,判断这个是否可以,如果这个可以那直接输出NO, 否则,输出 YES,因为这个是第二优
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
int T;
string s;
bool check()
{
stack<char> sta;
int flag = 1;
for (int i = 0; i < s.size(); ++i)
{
if (s[i] == '(')
{
sta.push('(');
}
else if (s[i] == ')')
{
if (sta.empty())
{
flag = 0;
break;
}
sta.pop();
}
}
return flag;
}
int main()
{
//IOS; cin.tie(0), cout.tie(0);
cin >> T;
while (T--)
{
cin >> s;
if (s[0] == '?')
{
s[0] = '(';
}
if (s[s.size() - 1] == '?')
{
s[s.size() - 1] = ')';
}
//cout << s << endl;
int countl = 0, countr = 0, countwen = 0;
for (int i = 0; i < s.size(); ++i)
{
if (s[i] == '(')
{
++countl;
}
else if (s[i] == ')')
{
++countr;
}
else if (s[i] == '?')
{
++countwen;
}
}
if (countwen == 0 || countwen == 1)
{
cout << "YES" << endl;
continue;
}
int needl = s.size() / 2 - countl;
int needr = s.size() / 2 - countr;
//cout << needl << " " << needr << endl;
//这里有一个思想,对于这些问号,我先填(肯定是最优的,就相当于,前面全是(, 后面全是),)这个要尽量靠后
//当)这个向前移动一位,这个就是第二优的情况,对于这个第二优,如果可以,那就是NO,如果不行,说明明后面不管怎么移也都是不行的
//所以这样之后只要判断()的最中间位置,这两个交换下位置即可
int cnt = 0;
if (needl != 0 && needr != 0)
{
for (int i = 0; i < s.size(); ++i)
{
if (s[i] == '?')
{
++cnt;
if (cnt < needl)
{
s[i] = '(';
}
else if (cnt == needl)
{
s[i] = ')';
}
else if (cnt == needl + 1)
{
s[i] = '(';
}
else
{
s[i] = ')';
}
}
}
//cout << s << endl;
if (check()) //检查次优是否可以达到
{
cout << "NO" << endl;
}
else
{
cout << "YES" << endl;
}
}
else
{
cout << "YES" << endl;
}
}
return 0;
}
/*
1
?((?(???
*/
做了1个半小时QWQ, 没做出来 > - <