1. 程式人生 > 其它 >hdu: Public Sale(博弈入門)

hdu: Public Sale(博弈入門)

Problem Description
雖然不想,但是現實總歸是現實,Lele始終沒有逃過退學的命運,因為他沒有拿到獎學金。現在等待他的,就是像FarmJohn一樣的農田生涯。

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

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

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

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

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

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

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


輸入樣例

4 2
3 2
3 5

輸出樣例

1
none
3 4 5

本題首先是反向思考,與取牌遊戲一致,取牌最後一步也可以看成取了1-n張牌,即最後將牌數取到<=0獲勝;
有一個注意點是當n>=m時lele第一次加價為m-n;
附ac程式碼
#include<bits/stdc++.h>
using namespace std;
int f[1110];
int n,m;
int sg(int p)
{
    bool g[1110]={0};
    for(int i=1;i<=n;++i)
    {
        int t=p-i;
        if(t<0) break;
        if(f[t]==-1) f[t]=sg(t);
        g[f[t]]=1;
    }
    for(int i=0;;++i)
    {
        if(!g[i]) return i;
    }
}
int main() { while(scanf("%d%d",&m,&n)==2) { if(n>=m) { for(int i=m;i<=n;++i) cout<<i<<" "; cout<<endl; continue; } memset(f,-1,sizeof(f)); f[0]=0; f[m]=sg(m); for(int i=0;i<=m;++i) if(f[i]==-1) f[i]=sg(i); if(!f[m]) printf("none\n"); else { for(int i=1;i<=n;++i) if(!f[m-i]) cout<<i<<" "; cout<<endl; } } return 0; }