藍橋杯 試題 歷屆試題 填字母遊戲 博弈+dfs剪枝

問題描述
  小明常常玩 LOL 遊戲上癮,一次他想挑戰K大師,不料K大師說:
  「咱們先來玩個空格填字母的遊戲,要是你不能贏我,就再別玩LOL了」。


  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

//解題思路:這一題是含有平局的無偏博弈問題。博弈問題通常思路:
f( 當前局勢  )
{
    臨界條件
    
    t = 負
    for( 全部步數 ){
        t = f(嘗試走一步)
        if( t==負 ) return 勝
        if( t==平 ) t = 平
    }
    return t
}
即嘗試一步,改變當前局勢,交給對方處理。每一方都儘量但願勝利,其次平局。
這裏直接用dfs()會超時,能夠用C++ map 將一個局勢 和 最終結果一一對應。 map.find()若是未找到 則 == map.end()  string.find()未找到返回-1
 
//實現代碼:
#include<iostream>
#include<string>
#include<map>
using namespace std;

//輸入 
int n;
string str;//當前狀態 

map<string,int> m;//鍵值對 用來把相同情況剪枝

int dfs(string str)// 返回  1 0 -1
{
    if( m.find(str)!=m.end() ){
        return m[str];//若是重複 剪枝 
    }
    
    if( (str.find("LO*")+1)||(str.find("*OL")+1)||(str.find("L*L")+1)){
        return m[str] = 1;//若是發現任意一個 則勝利(+1後返回值>=1 未找到返回0) 
    }
/***    上面代碼若是改成 
    if( str.find("LOL") ){
        return m[str] = -1;//若是發現任意一個 則勝利(+1後返回值>=1 未找到返回0) 
    } 
        邏輯上也是對的 但運行會超時 大概是多了沒必要要的遞歸  ***/
    if( str.find('*')==-1 ){
        return m[str] = 0;//沒有空位* 則平局 
    }
    
    int flat = -1;
    for(int i=0; i<str.length(); i++)
    {
        if( str[i] != '*' )
        {
            continue;
        }
        //嘗試兩種方式 
        str[i] = 'L';
        if( dfs(str)==-1 ){
            str[i] = '*';//這裏要先回溯爲傳入時的狀態 再存入map 
            return m[str] = 1;
        }
        
        if( dfs(str)==0 ){
            flat = 0;
        }
        
        str[i] = 'O';
        if( dfs(str)==-1 ){
            str[i] = '*';
            return m[str] = 1;
        }
        
        if( dfs(str)==0 ){
            flat = 0;
        }
        
        str[i] = '*';//回溯 
    }
    
    return m[str] = flat;
}

void solve()
{
    int res = dfs(str);
    cout<<res<<endl;
}

int main()
{
    cin>>n;
    while( n-- )
    {
        cin>>str;
        solve();
    }
    return 0;
}
相關文章
相關標籤/搜索