問題描述:
K大師在紙上畫了一行n個格子,要小明和他交替往其中填入字母。 1. 輪到某人填的時候,只能在某個空格中填入L或O 2. 誰先讓字母組成了“LOL”的字樣,誰獲勝。 3. 如果所有格子都填滿了,仍無法組成LOL,則平局。 小明試驗了幾次都輸了,他很慚愧,希望你能用計算機幫他解開這個謎。 本題的輸入格式為: 第一行,數字n(n<10),表示下面有n個初始局面。 接下來,n行,每行一個串,表示開始的局面。 比如:“******”, 表示有6個空格。“L****”, 表示左邊是一個字母L,它的右邊是4個空格。 要求輸出n個數字,表示對每個局面,如果小明先填,當K大師總是用最強着法的時候,小明的最好結果。 1 表示能贏 -1 表示必輸 0 表示可以逼平
輸入
4 *** L**L L**L***L L*****L
輸出
0 -1 1 1
問題分析:
首先,對於此問題,我們要明白,它是有偏博弈,還是無偏博弈。
無偏博弈:在組合博弈論里,無偏博弈是一類任意局勢對於游戲雙方都是平等的回合制雙人游戲。這里平等的意思是所有可行的走法僅僅依賴於當前的局勢,而與現在正要行動的是哪一方無關。換句話說,兩個游戲者除了先后手之外毫無區別。
有偏博弈:除無偏博弈外,其余博弈皆為有偏博弈
當填入一個字母時,我們要考慮兩個問題,一是是否形成了LOL這個字符串,二是是否還存在空格,如果是第一種情況,則說明對方輸了,我方贏了,如果不存在空格了,說明將有可能平局,因此,問題就簡化為對每一個要填的空,做上述的判斷,形成了一個遞歸。
代碼描述:
/*LOL填字游戲 我方先填 */ #include<iostream> #include<cstdlib> #include<string> using namespace std; int is_lol(string x); int main(){ string x; cout<<is_lol("***")<<endl; cout<<is_lol("L**L")<<endl; cout<<is_lol("L**L***L")<<endl; cout<<is_lol("L*****L")<<endl; return 0; } int is_lol(string x){ /*1表示能贏 0表示平局 -1表示輸 */ int len=x.length(); if(x.find("LOL")!=string::npos) return -1;//當我方開始填時已出現LOL時,則我方輸 if(x.find("*")==string::npos) return 0;//當沒有出現LOL時,且沒有空格則為平局 int ping=0;//先假設為平局 for(int i=0;i<len;i++){ if(x[i]=='*'){ x[i]='L'; switch(is_lol(x)) { case -1: return 1;//當我方填完后,出現LOL,則我方贏 case 0: ping=1;//當我方填完后,沒有空格,則為平局 } x[i]='O'; switch(is_lol(x)) { case -1: return 1;//當我方填完后,出現LOL,則我方贏 case 0: ping=1;//當我方填完后,沒有空格,則為平局 } x[i]='*'; } } if(ping) return 0;//如果存在平局,則結果為平局,否則即輸 return -1; }