【HDU】4915 Parenthese sequence 贪心

传送门:【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 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值