巴什博弈和4道巴什博奕題(入門級)

題目一:hdu1846

問題描述

各位勇敢者要玩的第一個遊戲是什麼呢?很簡單,它是這樣定義的:
1、 本遊戲是一個二人遊戲;
2、 有一堆石子一共有n個;
3、 兩人輪流進行;
4、 每走一步可以取走1…m個石子;
5、 最先取光石子的一方爲勝;

如果遊戲的雙方使用的都是最優策略,請輸出哪個人能贏。

巴什博弈

只有一堆n個物品,雙方輪流從這堆裏取出物品,規定每次至少取1個,最多取m個,先取完者獲勝。

1.如果物品n=m+1,如果先手取x個,那麼後手每次取m+1-x個,那麼後手必贏。
2.如果物品n=a*(m+1),每回合依然,先手取x個,後手每次取m+1-x個,a回合結束後,還是後手必贏。
3.如果物品n=a*(m+1)+b,此時先手先考慮,如果他採取最優策略,他可以先取b個石子,這樣他把n=a*(m+1)的局面扔給後手,此刻後手成爲了第二種情況的先手,他成爲了第二種情況的後手,這個時候的後手必贏。

規律

所以我們發現了,如果n%(m+1)==0,先手必敗,否則的話,後手必勝。

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int n,m,t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m; 
        int mm = n%(m+1);
        if(mm==0)
        {
            cout<<"second"<<endl; 
        }
        else
        {
            cout<<"first"<<endl;    
        }
    } 
    return 0;
}
稍微變形下

它就是:兩個人輪流報數,每次至少報一個,最多報m個,誰能報到大於等於n的人獲勝。
當然本質是一樣的
第二題:hdu2188

題目描述:

他決定通過捐款來決定兩人誰能入選。
選拔規則如下:
1、最初的捐款箱是空的;
2、兩人輪流捐款,每次捐款額必須爲正整數,並且每人每次捐款最多不超過m元(1<=m<=10)。
3、最先使得總捐款額達到或者超過n元(0<n<10000)的一方爲勝者,則其可以親赴災區服務。
我們知道,兩人都很想入選志願者名單,並且都是非常聰明的人,假設林隊先捐,請你判斷誰能入選最後的名單?

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int n,m,t;
    cin>>t;
    while(t--)        //目標爲n元 
    {
        cin>>n>>m; 
        if(n%(m+1)==0)
        {
            cout<<"Rabbit"<<endl;    
        }
        else 
        {
            cout<<"Grass"<<endl;    
        }
    }
    return 0;
}
PN分析

此類題目的通用方法:

P點: 即必敗點,某玩家位於此點,只要對方無失誤,則必敗;

N點: 即必勝點,某玩家位於此點,只要自己無失誤,則必勝。

我們可以打表遞推找些規律

第三題:hdu2147
題目描述:

Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she just playes the checkerboard game.The size of the chesserboard is nm.First of all, a coin is placed in the top right corner(1,m). Each time one people can move the coin into the left, the underneath or the left-underneath blank space.The person who can’t make a move will lose the game. kiki plays it with ZZ.The game always starts with kiki. If both play perfectly, who will win the game?
對於一個n
m的地圖,兩人輪流從地圖右上角開始移動硬幣,每次只能朝下走,朝左走,或者左下走,最先不能移動的人失敗。
很明顯,從右上角走到左下角共需要n-1+m-1步,朝左走或者朝右走是走了一步,朝左下的方向走是走了兩步。
似乎,這個題可以轉換成一模一樣的巴士博弈:一共要走(n+m-2)步,每人最少走一步,最多走兩步,先走完的人獲勝。
但是這樣考慮不對,因爲如果走到地圖的最下邊或者最左邊,剩下只能朝下走或者朝右走。
所以我們可以通過pn分析問題

  1. 首先玩家位於左下角時,此刻他不能移動,此刻他是必敗態P
1 2 3 4 5 6
1
2
3
4
5 p

2.再考慮(5 ,2)點,當玩家A位於(5,2)點時,玩家B只能往左走到達必敗點(5,1),說明此刻這個點,是必勝點N,同理可以推出(5,3)點,同理可以推出第五行和第一列的所有座標的狀態。

1 2 3 4 5 6
1 p
2 n
3 p
4 n
5 p n p n p n

3.然後我們此刻只能去推(4,2)點的狀態,因爲只有這個點的三個方向的狀態是確定的(4,1)(5,1)(5,2),如果玩家A位於(4,2)點,那麼玩家B移動硬幣的話,肯定要想辦法把玩家A引導到一個必敗狀態,而且他有的選,那就是移動到(5,1)所以(4,2)點就是必勝點。
然後也找出了遞推順序,先左下角,再兩邊。

1 2 3 4 5 6
1 p n p n p n
2 n n n n n n
3 p n p n p n
4 n n n n n n
5 p n p n p n

4.規律,當n和m都爲奇數時必敗,反之必勝

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0 && m==0)
        {
            break;
        }

        if(n&1 && m&1)
        {
            cout<<"What a pity!"<<endl;
        }
        else
        {
            cout<<"Wonderful!"<<endl;
        }    
    }
    return 0;
}
第四題:hdu2149

題目描述:
要種田得有田纔行,Lele聽說街上正在舉行一場別開生面的拍賣會,拍賣的物品正好就是一塊20畝的田地。於是,Lele帶上他的全部積蓄,衝往拍賣會。

後來發現,整個拍賣會只有Lele和他的死對頭Yueyue。

通過打聽,Lele知道這場拍賣的規則是這樣的:剛開始底價爲0,兩個人輪流開始加價,不過每次加價的幅度要在1~N之間,當價格大於或等於田地的成本價 M 時,主辦方就把這塊田地賣給這次叫價的人。

Lele和Yueyue雖然考試不行,但是對拍賣卻十分精通,而且他們兩個人都十分想得到這塊田地。所以他們每次都是選對自己最有利的方式進行加價。

由於Lele字典序比Yueyue靠前,所以每次都是由Lele先開始加價,請問,第一次加價的時候,
Lele要出多少才能保證自己買得到這塊地呢?

本題目包含多組測試,請處理到文件結束(EOF)。每組測試佔一行。
每組測試包含兩個整數M和N(含義見題目描述,0<N,M<1100)

對於每組數據,在一行裏按遞增的順序輸出Lele第一次可以加的價。兩個數據之間用空格隔開。
如果Lele在第一次無論如何出價都無法買到這塊土地,就輸出"none"。

思路

n=a*(x+m+1-x)+b
當b=0時,必輸,輸出"none"
如果不能一次買到既a!=0,就要加(m+1)的倍數錢,但是最多加m錢,這就矛盾了,所以如果不能一次買到,就是0;
如果能一次買到,出價區間爲[b,m],(哦,這個題面的n和m剛好是反過來的)。

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int m,n;
    while(cin>>m>>n)
    {
        if(m%(n+1)==0)
        {
            cout<<"none"<<endl;    
        }        
        else 
        {
            int k = m%(n+1);
            cout<<k;
            if(m/(n+1)==0)
            {
                for(int m=k+1;m<=n;++m)
                {
                    cout<<" "<<m;
                }
            }
            cout<<endl;
        }
    } 
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章