hdu 4915 Parenthese sequence (贪心+模拟)

题目大意:

一个序列中有左括号和右括号,还有问号,问号可以任意转换成左右括号。

问这个序列有多少种情况的转变使得这个序列变成合法的括号匹配序列。

思路分析:

首先我们分析一下,如何使得一个序列是合法的括号匹配序列。

我们很容易想到的是用栈模拟匹配过程。

当遇到左括号就进栈,当遇到右括号就让栈顶的左括号出栈。

那么在模拟的过程中,造成这个序列的不合法的原因只有当右括号来的时候,此时的栈已经为空。

这里补充一句,一旦一个序列给定,那么这里面的问号有多少变成左括号,多少变成右括号,是一定的。

看完以上的过程,也许你能想到这样的一个贪心策略。我们要保证这个序列有解,就让左括号尽量靠左。尽量保证栈内有左括号。

所以我们要做的,就是把问号的左边部分全部变成左括号,剩余的问号再变成右括号。

这样就判断他是否有解。

接下来的问题是判断多解,我们还是按照以上的贪心策略。

但是要退一步考虑。

设 这个序列里有  x 个问号, 其中 lef 个问号变成了左括号, rig 个问号变成了右括号。

那我们把刚好第 lef 个左括号变成右括号,第一个变成右括号的问号变成左括号。

((????))

如果按照第一种策略  就变成了

(((())))

再按照第二种策略  就变成了

((()()))

然后再去匹配一次,如果有解,那么就有多解。

thats all

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 1000005
#define MAXN 1000005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int l,r;
char str[maxn];
char tmp[maxn];
char stk[maxn];

bool judge(int len)//括号的匹配过程
{
    int top=-1;
    for(int i=0;i<len;i++)
    {
        if(tmp[i]=='('){
            stk[++top]='(';
        }
        else {
            if(top==-1)return false;
            else top--;
        }
    }

    if(top==-1)return true;
    return false;
}
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        int len=strlen(str);

        if(len&1){
            printf("None\n");
            continue;
        }
        l=r=0;
        int cntl=0,cntr=0;
        for(int i=0;i<len;i++)
        {
            if(str[i]=='(')l++;
            else if(str[i]==')')r++;
        }

        cntl=(len-2*l)/2;//计算多少个问号变成左括号
        cntr=(len-2*r)/2;//多少个问号变成右括号

        int t=cntl;
        int posl=-1,posr=-1;
        for(int i=0;i<len;i++)
        {
            if(str[i]=='?')
            {
                if(t>0)
                {
                    tmp[i]='(';
                    t--;
                    if(t==0)posl=i;//最后一个变成左括号的问号的位置
                }
                else {
                    tmp[i]=')';
                    if(posr==-1)posr=i;//最后一个变成右括号的问号的位置
                }
            }
            else tmp[i]=str[i];
        }

        if(!judge(len))printf("None\n");
        else {
            if(posl==-1 || posr==-1)printf("Unique\n");
            else {
                swap(tmp[posl],tmp[posr]);
                if(judge(len))printf("Many\n");
                else printf("Unique\n");
            }
        }
    }
    return 0;
}

hdu 4915 Parenthese sequence (贪心+模拟)

时间: 2024-10-26 13:06:18

hdu 4915 Parenthese sequence (贪心+模拟)的相关文章

hdu 4915 Parenthese sequence(模拟)2014多校训练第5场

Parenthese sequence                                                                     Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description bobo found an ancient string. The string contains only t

HDU 4915 Parenthese Sequence 思维+模拟

题意:给出括号序列s,其中有'?'表示可以为'('或')'.|s|<=1e6,问将这些'?'代替后,s是否合法,若合法 是否有多解? 首先:把已经匹配的丢出去,不影响序列的合法性则 维护前缀i '('最多和最少未匹配的个数,对后缀i维护')'最多和最少未匹配的个数  (还剩个数)当max[i]<0 说明某个'('或')'不够匹配为无解.假如后缀i最少有x个')',则前缀i-1最少要有x个'(' 后缀i最多有y个')' 前缀i-1'('个数不多于y则前面左括号的范围就为[x,y]若y-x+1&g

HDU 4915 Parenthese sequence

HDU 4915 Parenthese sequence 题目链接 题意:给定一个有?的左右括号串,?能替代为'('或')',问括号匹配是否唯一或多种或不可能 思路:先从右往左扫一边,维护一个up, down表示当前位置右边右括号剩余个数的上限和下限,如果维护完后起始位置的下限为0,那么就是可以的,因为为0就代表没有多余的右括号.然后在从左往右扫一遍,和上面一样的处理,只是遇到每个问号的位置时,试一下左括号和右括号,如果都满足,表示这个位置能放左右括号,是多种可能,如果所有?都只有唯一的方法,那

hdu 4915 Parenthese sequence(高效)

题目链接:hdu 4915 Parenthese sequence 题目大意:给定一个序列,由(,),?组成?可以表示(或者),问说有一种.多种或者不存在匹配. 解题思路:从左向右,从右向左,分别维护左括号和右括号可能的情况,区间上下界.如果过程中出现矛盾,则为None,否则要判断唯一解还是多解.枚举每个问号的位置,假设该问号可为左右括号,则有多解. #include <cstdio> #include <cstring> #include <algorithm> us

HDU 4915 Parenthese sequence(瞎搞题)

从左向右扫一遍左括号的最大值,与最小值. 从右向左扫一遍右括号的最大值,与最小值. 比较最大值中的最小数与最小中的最大数看能否有交集,0个,1个或者多个. Parenthese sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 301    Accepted Submission(s): 129 Problem De

HDU 4915 Parenthese sequence _(:зゝ∠)_ 呵呵

呵呵不是我做的 #include <cstdio> #include <cstring> #include <algorithm> const int N = 1000000 + 10; char s[N]; int d[N], num[N]; int main() { while (~scanf("%s", s)) { memset(num, 0, sizeof num); int len = strlen(s); int f = 1, v = 0

HDU 4915 Parenthese sequence _(:зゝ∠)_ 哈哈

哦,我没做 #include <cstdio> #include <cstring> #include <algorithm> const int N = 1000000 + 10; char s[N]; int d[N], num[N]; int main() { while (~scanf("%s", s)) { memset(num, 0, sizeof num); int len = strlen(s); int f = 1, v = 0;

hdu 4915 Parenthese sequence 多校第五场

推断一个序列是否是有效是简单的. 可是推断序列是不是有多个解会出问题. 那么从i=0 ~l 假设读到问号,推断该问号成为(能否有效,该问号为)是否有效. 假设都有效,则必有多个解. 假设都无效,则无解. 假设一个有效,则把问号改成有效的括号. 代码实现例如以下 #include<stdio.h> #include<string.h> char s[1000005],tp[1000005]; int l; int pd() { int zuo,you,num,i; num=0; zu

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;