巴什游戲與SG函數(shù)

巴什游戲(Bash Game)

裸題:HDU 1846 Brave Game

題目鏈接:https://vjudge.net/problem/HDU-1846

題意:有 n 顆石子,甲先取,乙后取纫骑,每次可以拿 1 \sim m 顆石子,輪流拿下去登颓,拿到最后一顆的人獲勝。

思路:動(dòng)態(tài)規(guī)劃红氯。時(shí)間復(fù)雜度為 10^2 \times 10^3 \times 10^3 = 10^8框咙,本題數(shù)據(jù)不是很強(qiáng),可以通過(guò)痢甘。

AC代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

using namespace std;
const int N = 1010;
int f[N];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        
        memset(f, 0, sizeof f);
        
        for(int i = 1; i <= m; i++) f[i] = 1;
        
        for(int i = m + 1; i <= n; i++)
        {
            int t = 1;
            for(int j = 1; j <= m; j++) t &= f[i - j];
            // 如果有一個(gè)是必?cái)B(tài)喇嘱,那么這個(gè)狀態(tài)就是必勝態(tài)
            // 如果全是必勝態(tài),那么這個(gè)狀態(tài)就是必?cái)B(tài)
            f[i] = (t == 1 ? 0 : 1);
        }
        
        if(f[n])    puts("first");
        else    puts("second");
    }
    
    return 0;
}

上面動(dòng)態(tài)規(guī)劃的求解過(guò)程非常直觀塞栅,但時(shí)間復(fù)雜度略高者铜,所以,我們選擇將 n=23,m=2 的結(jié)果打印出來(lái)放椰,看看有沒(méi)有什么規(guī)律作烟。

image.png

可以發(fā)現(xiàn),如果 n3 的倍數(shù)砾医,則后手獲勝拿撩;否則,先手獲勝如蚜。

這個(gè)規(guī)律怎么解釋呢压恒?先來(lái)看兩種簡(jiǎn)單的情況:

  1. 當(dāng) n \leq m 時(shí),由于一次最少拿 1 個(gè)错邦、最多拿 m 個(gè)涎显,甲可以一次拿完,先手贏兴猩。

  2. 當(dāng) n=m+1 時(shí),無(wú)論甲拿走多少個(gè)(1 \sim m 個(gè))早歇,剩下的都多于 1 個(gè)倾芝、少于等于 m 個(gè)讨勤,乙都能一次拿走剩余的石子,后手取勝晨另。

上面兩種情況可以擴(kuò)展為以下兩種情況:

  1. 如果 n \% (m+1)=0潭千,即 nm+1 的整數(shù)倍,那么不管甲拿多少借尿,例如 k 個(gè)刨晴,乙都拿 m+1-k 個(gè),使得剩下的永遠(yuǎn)是 m+1 的整數(shù)倍路翻,直到最后的 m+1 個(gè)狈癞,所以后拿的乙一定贏。

  2. 如果 n \% (m+1)!=0茂契,即 n 不是 m+1 的整數(shù)倍蝶桶,還有余數(shù) r,那么甲拿走 r 個(gè)掉冶,剩下的是 m+1 的倍數(shù)真竖,這樣就轉(zhuǎn)移到了情況1,相當(dāng)于甲厌小、乙互換恢共,結(jié)果是甲贏。

在這個(gè)拿石子的游戲里璧亚,對(duì)于后拿的乙來(lái)說(shuō)是很不利的讨韭,只有在 n \% (m+1)=0 的情況下乙才能贏,在其他情況下都是甲贏涨岁。

AC代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int n, m;
        cin >> n >> m;
        if(n % (m + 1) == 0)    puts("second");
        else    puts("first");
    }
    
    return 0;
}

本題是最經(jīng)典也是最簡(jiǎn)單的巴什游戲拐袜,在編程時(shí)可以用動(dòng)態(tài)規(guī)劃,也可以直接按周期性變化規(guī)律做求余計(jì)算梢薪。但是蹬铺,如果遇到更復(fù)雜的游戲,將很難分析秉撇。有一種高級(jí)的分析方法甜攀,即Sprague-Grundy函數(shù),是該類(lèi)問(wèn)題的通用方法琐馆。

Sprague-Grundy函數(shù)

首先介紹一些概念:

公平組合游戲(Impartial Combinatorial Game, ICG)

若一個(gè)游戲滿(mǎn)足:

  1. 由兩名玩家交替行動(dòng)规阀;
  2. 在游戲進(jìn)程的任意時(shí)刻,可以執(zhí)行的合法行動(dòng)與輪到哪名玩家無(wú)關(guān)瘦麸;
  3. 不能行動(dòng)的玩家判負(fù)谁撼;

則稱(chēng)該游戲?yàn)橐粋€(gè)公平組合游戲。

常見(jiàn)的棋類(lèi)游戲滋饲,比如圍棋厉碟,就不是公平組合游戲喊巍。因?yàn)閲褰粦?zhàn)雙方分別只能落黑子和白子,勝負(fù)判定也比較復(fù)雜箍鼓,不滿(mǎn)足條件 2 和條件 3崭参。

有向圖游戲

給定一個(gè)有向無(wú)環(huán)圖,圖中有一個(gè)唯一的起點(diǎn)款咖,在起點(diǎn)上放有一枚棋子何暮。兩名玩家交替地把這枚棋子沿有向邊進(jìn)行移動(dòng),每次可以移動(dòng)一步铐殃,無(wú)法移動(dòng)者判負(fù)海洼。該游戲被稱(chēng)為有向圖游戲。

任何一個(gè)公平組合游戲都可以轉(zhuǎn)化為有向圖游戲背稼。具體方法是贰军,把每個(gè)局面看成圖中的一個(gè)節(jié)點(diǎn),并且從每個(gè)局面向沿著合法行動(dòng)能夠到達(dá)的下一個(gè)局面連有向邊蟹肘。

Mex運(yùn)算

設(shè) S 表示一個(gè)非負(fù)整數(shù)集合词疼。定義 mex(S) 為求出不屬于集合 S 的最小非負(fù)整數(shù)的運(yùn)算,即:
mex(S) = min\left\{ x \right\},\ x屬于自然數(shù)且x不屬于S

SG函數(shù)

在有向圖游戲中帘腹,對(duì)于每個(gè)節(jié)點(diǎn) x贰盗,設(shè)從 x 出發(fā)共有 k 條有向邊,分別到達(dá)節(jié)點(diǎn) y_1, y_2, …, y_k阳欲,定義 SG(x)x 的后繼節(jié)點(diǎn) y_1, y_2, …, y_k 的 SG 函數(shù)值構(gòu)成的集合再執(zhí)行 mex 運(yùn)算的結(jié)果舵盈,即:

SG(x) = mex(\left\{SG(y_1),\ SG(y_2),\ …,\ SG(y_k)\right\})

特別地,整個(gè)有向圖游戲 G 的 SG 函數(shù)值被定義為有向圖游戲起點(diǎn) s 的 SG 函數(shù)值球化,即SG(G) = SG(s)秽晚。

有向圖游戲的和

設(shè) G_1, G_2, …, G_mm 個(gè)有向圖游戲。定義有向圖游戲 G筒愚,它的行動(dòng)規(guī)則是任選某個(gè)有向圖游戲 G_i赴蝇,并在 G_i 上行動(dòng)一步。G 被稱(chēng)為有向圖游戲 G_1, G_2, …, G_m 的和巢掺。

有向圖游戲的和的 SG 函數(shù)值等于它包含的各個(gè)子游戲 SG 函數(shù)值的異或和句伶,即:

SG(G) = SG(G_1) \oplus SG(G_2) \oplus … \oplus SG(G_m)

定理

有向圖游戲的某個(gè)局面必勝,當(dāng)且僅當(dāng)該局面對(duì)應(yīng)節(jié)點(diǎn)的SG函數(shù)值大于0陆淀。

有向圖游戲的某個(gè)局面必?cái)】加啵?dāng)且僅當(dāng)該局面對(duì)應(yīng)節(jié)點(diǎn)的SG函數(shù)值等于0。

至此轧苫,相關(guān)概念就介紹完了楚堤,接著,我們嘗試用SG函數(shù)求解HDU 1846的巴什游戲。

AC代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

using namespace std;
const int N = 1010;
int sg[N], s[N];

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int n, m;
        cin >> n >> m;
        
        memset(sg, 0, sizeof sg);
        
        for(int i = 1; i <= n; i++)
        {
            memset(s, 0, sizeof s);
            
            // 把i的后繼結(jié)點(diǎn)放到集合s中
            for(int j = 1; j <= m && i - j >= 0; j++)   s[sg[i - j]] = 1;
            
            // 計(jì)算sg[i]
            for(int j = 0; j <= n; j++)
            {
                if(!s[j])
                {
                    sg[i] = j;
                    break;
                }
            }
        }
        
        if(sg[n])   puts("first");
        else    puts("second");
    }
    
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末身冬,一起剝皮案震驚了整個(gè)濱河市鳄袍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吏恭,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件重罪,死亡現(xiàn)場(chǎng)離奇詭異樱哼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)剿配,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)搅幅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人呼胚,你說(shuō)我怎么就攤上這事茄唐。” “怎么了蝇更?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵沪编,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我年扩,道長(zhǎng)蚁廓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任厨幻,我火速辦了婚禮相嵌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘况脆。我一直安慰自己饭宾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布格了。 她就那樣靜靜地躺著看铆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪笆搓。 梳的紋絲不亂的頭發(fā)上性湿,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音满败,去河邊找鬼肤频。 笑死,一個(gè)胖子當(dāng)著我的面吹牛算墨,可吹牛的內(nèi)容都是我干的宵荒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼报咳!你這毒婦竟也來(lái)了侠讯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤暑刃,失蹤者是張志新(化名)和其女友劉穎厢漩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體岩臣,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溜嗜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了架谎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炸宵。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谷扣,靈堂內(nèi)的尸體忽然破棺而出土全,到底是詐尸還是另有隱情,我是刑警寧澤会涎,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布裹匙,位于F島的核電站,受9級(jí)特大地震影響在塔,放射性物質(zhì)發(fā)生泄漏幻件。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一蛔溃、第九天 我趴在偏房一處隱蔽的房頂上張望绰沥。 院中可真熱鬧,春花似錦贺待、人聲如沸徽曲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秃臣。三九已至,卻和暖如春哪工,著一層夾襖步出監(jiān)牢的瞬間奥此,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工雁比, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稚虎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓偎捎,卻偏偏與公主長(zhǎng)得像蠢终,于是被迫代替她去往敵國(guó)和親序攘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359