HDU 4915 (贪心)

题目链接:点击这里

题意:给出一个序列, 其中含有左右括号或者问号, 问号既可以是左括号也可以是右括号。 求合法序列是唯一存在还是不存在还是存在多种。

定义一个数组 a 和它的前缀序列sum, 左括号对应下标的 ai=1 , 右括号对应下标的 ai=1 , 一个括号序列合法当且仅当:
f(x)={sumi0sumn=0(1in)

问号需要提供多少个左括号和右括号可以算出来, 然后贪心的左边全部填左括号右边全部填右括号, 构造上述数列就可以判断是否有解了。 至于解的数量, 右可以用一次贪心, 将问号变成左括号最右边的那个逆转, 类似的问号变成右括号最左边的逆转, 然后继续判断序列合法就可以了。

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000005

char a[maxn];
int s[maxn];
int sum[maxn];
int n;
int l, r, x;

int main () {
    while (scanf ("%s", a) == 1) {
        n = strlen (a);
        if (n&1) {
            printf ("None\n");
            continue;
        }
        l = 0, r = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] == '(') l++;
            else if (a[i] == ')') r++;
        }
        x = n-l-r;
        int pos1, pos2;
        int L = n/2-l, R = n/2-r;//还需要的左括号和右括号
        if (L < 0 || R < 0) {
            printf ("None\n");
            continue;
        }
        int cnt1 = L, cnt2 = R; 
        for (int i = 0; i < n; i++) {
            if (a[i] == '(') s[i] = 1;
            else if (a[i] == ')') s[i] = -1;
            else if (cnt1) {
                s[i] = 1, cnt1--;
                if (cnt1 == 0) pos1 = i;
            }
            else {
                if (cnt2 == R) pos2 = i;
                s[i] = -1, cnt2--;
            }
            sum[i] = (i == 0 ? s[i] : s[i]+sum[i-1]);
        }

        for (int i = 0; i < n; i++) if (sum[i] < 0) {
            printf ("None\n");
            goto out;
        }
        if (L == 0 || R == 0) {
            printf ("Unique\n");
            continue;
        }
        s[pos1] = -1, s[pos2] = 1;
        for (int i = 0; i < n; i++) {
            sum[i] = (i == 0 ? s[0] : s[i]+sum[i-1]);
            if (sum[i] < 0) {
                printf ("Unique\n");
                goto out;
            }
        }
        printf ("Many\n");

        out: ;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值