標籤:blog os io for 2014 問題 ar amp
題目大意:
一個序列中有左括弧和右括弧,還有問號,問號可以任意轉換成左右括弧。
問這個序列有多少種情況的轉變使得這個序列變成合法的括弧匹配序列。
思路分析:
首先我們分析一下,如何使得一個序列是合法的括弧匹配序列。
我們很容易想到的是用棧類比匹配過程。
當遇到左括弧就進棧,當遇到右括弧就讓棧頂的左括弧出棧。
那麼在類比的過程中,造成這個序列的不合法的原因只有當右括弧來的時候,此時的棧已經為空白。
這裡補充一句,一旦一個序列給定,那麼這裡面的問號有多少變成左括弧,多少變成右括弧,是一定的。
看完以上的過程,也許你能想到這樣的一個貪心策略。我們要保證這個序列有解,就讓左括弧盡量靠左。盡量保證棧內有左括弧。
所以我們要做的,就是把問號的左邊部分全部變成左括弧,剩餘的問號再變成右括弧。
這樣就判斷他是否有解。
接下來的問題是判斷多解,我們還是按照以上的貪心策略。
但是要退一步考慮。
設 這個序列裡有 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-6typedef 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;}