hdu4915

Parenthese sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 82    Accepted Submission(s): 25

Problem Description
bobo found an ancient string. The string contains only three charaters -- "(", ")" and "?".
bobo would like to replace each "?" with "(" or ")" so that the string is valid (defined as follows). Check if the way of replacement can be uniquely determined.
Note:
An empty string is valid. If S is valid, (S) is valid. If U,V are valid, UV is valid.
 
Input
The input consists of several tests. For each tests:
A string s1s2…sn (1≤n≤106).
 
Output
For each tests:
If there is unique valid string, print "Unique". If there are no valid strings at all, print "None". Otherwise, print "Many".
 
Sample Input
??
????
(??
 
Sample Output
Unique
Many
None
 
Author
Xiaoxu Guo (ftiasch)
 
Source
 
Recommend
We have carefully selected several similar problems for you:  4919 4918 4917 4916 4914

题意:问号替换成大于号或小于号,求是否有唯一可行方案、多解、无解。(括号规则:和平时运算的括号规则一致)

题解:贪心!O(n)!

我们开三个双向队列,用来记录左括号、右括号、问号的位置。

先从头开始扫,左括号和问号直接入相应队列,遇到右括号就用左括号或问号抵消掉(不入队)。优先用已记录的队列中最右边的左括号,左括号没了的话就用最左边的问号,如果也没有就说明无解。因为越左边的左括号越有用(能选择更多的括号相组合),越靠边的问号越没用(容易只有一种选择),我们先把没用的都用掉,留下比较好用的。

扫完一遍后,还会剩下一些左括号和问号,我们从最右边的左括号开始消,用最右边的问号,如果最右边的问号都比最右边的左括号小了就无解。

这一遍完了以后,就只剩下问号队列还有东西了。是奇数个的话,返回无解。0个的话,返回有唯一解。

然后就是比较难想的部分,剩下偶数个问号,肯定有解,该怎么判断有多少种解呢?

我用的是这样的方法:拿最中间那个(也就是最好用的问号),把它变成左括号,递归调用本函数判断是否有解(函数可以设一个参数,为0的时候是正常调用,为1的时候是只返回有没有解,不判断单解多解),然后再把它变成右括号,判断是否有解。都有解就是多解,只有一个有解就是单解。

这样我们这个函数只扫两次O(n),然后递归调用两次,哇,还是O(n),我自己都怕。

虽然正确性我也没有证明,不过AC了,这肯定是因为最中间的问号,就是这么碉!(不,大概是有多解的时候最中间的问号肯定有多解)

1.若剩下4个或更多的问号,则肯定是多解。

例如,设处理后的序列为: “*a*b*c*d*” ,a、b、c、d为4个问号,星号为其他。当a和d问号变为“()”时,中间的b和c肯定可以取“()”或“)(”。

2.若剩下2个问号,拿左边那个,把它变成左括号,递归调用本函数判断是否有解(函数可以设一个参数type,type为0的时候是正常调用,type为1的时候是只返回有没有解,不判断单解多解),然后再把它变成右括号,判断是否有解。都有解就是多解,只有一个有解就是单解。

    只剩2个问号的话,这两个问号是成对的,就是说这两个问号之外,其他括号都有一一对应,这两个括号肯定不会是“((”或者“))”的情况,只有“()”和“)(”的情况。

而“()”的情况肯定可行,只用判断第一个问号的“)”情况,可行的话就多解,不可行就单解。

感谢1楼的评论让我多想了一下,不然我也不懂我原来的解法为什么对。

新的代码(加了注释)(用了手工开栈,要用VC++编译器)(提交选C++):

 #pragma comment(linker, "/STACK:102400000,102400000")

 #include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll __int64
#define usint unsigned int
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,x,n) for(int i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) printf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1.out","w",stdout) char s[];
int len; int farm(bool type) {///type0是要判断多解的,type1只要有解就返回1
int i,j,q;
int l[],r[],b[][];///三个双向队列,存储3种东西
memset(l,,sizeof(l));
memset(r,,sizeof(r));
for(i=; i<len; i++) {
if(s[i]=='(') q=;
else if(s[i]==')')q=;
else q=;
if(q==) {///发现右括号,需要用左括号来消
if(r[]-l[]==) {///左括号不够,则用问号来消
if(r[]-l[]>) l[]++;
else {
return ;///问号也不够,就无解
}
} else r[]--;///左括号够,删除最右边的左括号来抵消这个右括号
} else b[q][r[q]++]=i;///将该元素加入相应队列
}
while((l[]<r[])&&(l[]<r[]) && (b[][r[]-])>b[][r[]-]) {///将最右边的左括号用最右边的问号来消
--r[];
r[]--;
}
if(l[]<r[])return ;///消不完左括号,则返回无解
if((r[]-l[])&==)return ;///剩下奇数个问号,返回无解
if(l[]==r[])return ;///不剩下问号,返回单解 if(type==)return ;///如果是不用判断是否多解的情况,直接返回1。
///下面剩了偶数个问号存在b[2]里 if(r[]-l[]>)return ;///若大于2个问号,则肯定多解
else{///若等于2个问号,则"()"肯定可行,试验")("是否可行
s[b[][l[]]]=')';
if(farm())return ;///可行则多解,不行则单解
else return ;
}
} int main() {
int i,j,k,q,ans;
while(scanf("%s",s)!=EOF) {
len=strlen(s);
ans=farm();
if(ans==) puts("None");
else if(ans==) puts("Unique");
else puts("Many");
}
return ;
}

hdu4915 Parenthese sequence 贪心O(n)解法(new)的更多相关文章

  1. hdu 4915 Parenthese sequence(模拟)2014多培训学校5现场

    Parenthese sequence                                                                     Time Limit: ...

  2. HDU5014Number Sequence(贪心)

    HDU5014Number Sequence(贪心) 题目链接 题目大意: 给出n,然后给出一个数字串,长度为n + 1, 范围在[0, n - 1].然后要求你找出另外一个序列B,满足上述的要求,而 ...

  3. 【题解】Cut the Sequence(贪心区间覆盖)

    [题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...

  4. hdu_5783_Divide the Sequence(贪心)

    题目链接:hdu_5783_Divide the Sequence 题意: 给你一个数列,让你分尽可能多的段,并且保证每一段的前缀和都不小于0 题解: 从后往前xjb贪心就行了 #include< ...

  5. hdu 5783 Divide the Sequence 贪心

    Divide the Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5783 Description Alice has a seq ...

  6. Codeforces Beta Round #11 A. Increasing Sequence 贪心

    A. Increasing Sequence 题目连接: http://www.codeforces.com/contest/11/problem/A Description A sequence a ...

  7. hdu 6047 Maximum Sequence 贪心

    Description Steph is extremely obsessed with “sequence problems” that are usually seen on magazines: ...

  8. 【BZOJ1345】[Baltic2007]序列问题Sequence 贪心+单调栈

    [BZOJ1345][Baltic2007]序列问题Sequence Description 对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和a ...

  9. CF3D Least Cost Bracket Sequence 贪心

    Least Cost Bracket Sequence CodeForces - 3D 题目描述 This is yet another problem on regular bracket sequ ...

随机推荐

  1. [NOIP2012] 提高组 洛谷P1079 Vigenère 密码

    题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...

  2. [MacOS NSAlert的使用]

    源:http://helloitworks.com/863.html NSAlert用于弹出一个确认对话框,在程序中被广泛地使用.常见的场景是用户删除数据,会弹出对话框给用户确认,免得用户不小心导致了 ...

  3. python 集合、函数和文件操作

    1.set集合 set集合是一个无序.不可重复.可嵌套的序列,基本功能是进行成员关系测试和删除重复元素,可以使用大括号({})或者 set()函数创建集合,注意:创建一个空集合必须用 set() 而不 ...

  4. 使用dom4j解析XML文档

    dom4j的包开源包,不属于JDK里面,在myeclipse中要单独导入在项目中,这里不累赘了 做这个过程,很慢,因为很多方法没用过不熟悉,自己得去查帮助文档,而且还得去试,因为没有中文版,英文翻译不 ...

  5. 【Beta版本】冲刺-Day7

    队伍:606notconnected 会议时间:12月15日 目录 一.行与思 二.站立式会议图片 三.燃尽图 四.代码Check-in 一.行与思 张斯巍(433) 今日进展:修改界面,应用图标 明 ...

  6. POJ3254Corn Fields(状态压缩DP入门)

    题目链接 题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一 ...

  7. JavaWeb---总结(十二)Session

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...

  8. Emgu学习之(四)——图像阈值

    http://www.cnblogs.com/CoverCat/p/5043833.html Visual Studio Community 2015 工程和代码:http://pan.baidu.c ...

  9. 为什么springMVC和Mybatis逐渐流行起来了?

    http://www.zhihu.com/question/36032573 https://github.com/bingoohuang/eql

  10. Linux 中,如何显示 (gcc)make时实际执行命令

    问题: 调试编译问题,如何获取,GCC(或许make)时,实际编译器和链接器正在执行的命令? 解决方法: 方法一:通用方法 使用dry run,如下 $ make -n 这将显示make 命令正在试图 ...