传送门:【HDU】4915 Parenthese sequence
题目分析:本题我实在是无力了。。比赛的时候没有做出来,后来一对数据发现有一种情况忘记考虑结果跪了一组数据。。。
我的思路是,首先将能够配对的括号先去掉,反正不影响结果。然后用剩下的字符循环。
首先从左到右,遇到左括号,计数器加一,如果遇到的是问号,入栈,如果遇到的是右括号,我们看是否右括号的数量大于左括号+问号的个数,大于那么肯定无解了!这一轮判断结束后,我们看是否左括号加问号的个数等于右括号的个数或者恰好比右括号大一,此时,如果有问号,那么需要全部变成左括号,如果有一个问号变成右括号就会导致无解!我们将这些问号必须变成左括号的直接变成左括号,因为他们的属性是定了的,不会再变成右括号了,不影响结果。同理我们从右到左再做一次,当然判断条件有些不同而已。
我们不断进行这一过程直到相邻两次栈中问号的个数保持不变(或者每次过程中的子过程结束后栈中无问号,此时必定唯一解)。
最后如果栈中有问号剩余就是多解(因为所有必须变成问号的都已经变了,剩下的都不是必须变的,而且只会剩下偶数个),没有则单解。
PS:算法到底有没有问题我不清楚,虽然感觉这样基本没问题了。。。如果有数据可以卡掉我的代码请一定要告诉我!谢谢!
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
const int MAXN = 1000005 ;
char a[MAXN] ;
int S[MAXN] ;
int match ( int n ) {
int cnt = 1 ;
a[0] = 0 ;
FOR ( i , 2 , n ) {
if ( a[cnt] == '(' && a[i] == ')' )
-- cnt ;
else
a[++ cnt] = a[i] ;
}
a[cnt + 1] = 0 ;
return cnt ;
}
void solve () {
int n = strlen ( a + 1 ) ;
if ( n & 1 ) {
printf ( "None\n" ) ;
return ;
}
int pre , cnt , top = 0 ;
do {
pre = top ;
n = match ( n ) ;
top = cnt = 0 ;
FOR ( i , 1 , n ) {
if ( a[i] == '(' )
++ cnt ;
else if ( a[i] == '?' )
S[top ++] = i ;
else if ( a[i] == ')' ) {
-- cnt ;
if ( cnt + top < 0 ) {//右括号比左括号+能变成左括号的还多,无解
printf ( "None\n" ) ;
return ;
}
}
if ( cnt + top <= 1 ) {//必须变左括号的强制变左括号
cnt += top ;
while ( top )
a[S[-- top]] = '(' ;
}
}
if ( !top ) {
printf ( "Unique\n" ) ;
return ;
}
n = match ( n ) ;
top = cnt = 0 ;
REV ( i , n , 1 ) {
if ( a[i] == ')' )
++ cnt ;
else if ( a[i] == '?' )
S[top ++] = i ;
else if ( a[i] == '(' ) {
-- cnt ;
if ( cnt + top < 0 ) {//左括号比右括号+能变成右括号的还多,无解
printf ( "None\n" ) ;
return ;
}
}
if ( cnt + top <= 1 ) {//必须变右括号的强制变右括号
cnt += top ;
while ( top )
a[S[-- top]] = ')' ;
}
}
if ( !top ) {
printf ( "Unique\n" ) ;
return ;
}
} while ( top != pre ) ;
if ( !top )
printf ( "Unique\n" ) ;
else
printf ( "Many\n" ) ;
}
int main () {
while ( ~scanf ( "%s" , a + 1 ) )
solve () ;
return 0 ;
}