goj 小游戏(棋盘博弈)

Problem Description:

最近kiki无事可做,于是他想玩棋盘游戏。棋盘的大小是n * m。首先,棋子放置在右上角(1,m)。 每次可以将棋子向左方,下方或左下方移动一个位置。当移动到(n,1)时就无法移动,无法移动的人失败。 kiki和bibi一起玩。游戏总是从kiki开始。 如果两者都完美发挥,谁会赢得比赛?

Input:

输入包含多个测试用例。 每行包含两个整数n,m(0 <n,m <= 2000)。 当n = 0和m = 0时输入终。

Output:

如果kiki赢,输出kiki;如果bibi赢,输出bibi。

Sample Input:

5 3
5 4
6 6
0 0

Sample Output:

bibi
kiki
kiki
解题思路:这道题比赛的时候推算了半天(QAQ表示当时还没学到博弈)才发现只要给出的n*m的结果是奇数则后手(bibi)就胜利,否则(偶数)先手(kiki)胜利。
证明:贴一张P/N图关于先手的输赢状态:

说明:状态P:先手只要最后是状态P,即此时无法再移动,则后手必赢,先手必输。

状态N:先手只要最后是状态N,后手就无法再移动,即先手必赢,后手必输。

现在关于P,N的求解有三个规则(前提:两者移动的每一步都保证是最优策略)

(1):最终态都是P

(2):按照游戏规则,到达当前态的前态都是N的话,当前态是P

(3):按照游戏规则,到达当前态的前态至少有一个P的话,当前态是N

综上,通过P/N图的分布规律,可以得出结论:如果n*m是偶数,则先手必赢,否则后手必赢。
AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int n,m;
 5     while(cin>>n>>m && (m+n)){
 6         if(m*n%2==0)cout<<"kiki"<<endl;//只要n*m为偶数,则先手必赢
 7         else cout<<"bibi"<<endl;//否则后手必赢
 8     }
 9     return 0;
10 }

 杭电hdu2147和此题几乎完全一样,只是输出不一样而已。题目链接:hdu 2147 kiki's game

 AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,m;
 6     while(cin>>n>>m && (m+n)){
 7         if(m*n%2)cout<<"What a pity!"<<endl;//先手必输
 8         else cout<<"Wonderful!"<<endl;//先手必赢
 9     }
10     return 0;
11 }
原文地址:https://www.cnblogs.com/acgoto/p/9058529.html