题目一: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 n*m.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
123456
1
2
3
4
5p

2.再考虑(5 ,2)点,当玩家A位于(5,2)点时,玩家B只能往左走到达必败点(5,1),说明此刻这个点,是必胜点N,同理可以推出(5,3)点,同理可以推出第五行和第一列的所有坐标的状态。

123456
1p
2n
3p
4n
5pnpnpn

3.然后我们此刻只能去推(4,2)点的状态,因为只有这个点的三个方向的状态是确定的(4,1)(5,1)(5,2),如果玩家A位于(4,2)点,那么玩家B移动硬币的话,肯定要想办法把玩家A引导到一个必败状态,而且他有的选,那就是移动到(5,1)所以(4,2)点就是必胜点。
然后也找出了递推顺序,先左下角,再两边。

123456
1pnpnpn
2nnnnnn
3pnpnpn
4nnnnnn
5pnpnpn

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;
}
Last modification:September 19th, 2019 at 12:06 am
如果觉得我的文章对你有用,请随意赞赏