Recover an RBS

 

 传送门

题意:

原先的一个常规的算术表达式中的一些位置的 ( 或者 ) 被 ? 替代了,题目给出一个有字符串,要求将 ? 补全, 如果 ? 的补全方法只有一种输出 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, 没做出来 > - <

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值