威佐夫博弈

6,024 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

最近准备公司内部的算法分享会,在找合适的算法题,发现一篇四年前参加的比赛题,比较有意思,分享给大家。

原题链接

题目描述

A single chess queen is placed somewhere on a  grid of 10000*10000 squares.Lao Wang and Xiao Ren ready to play a game The rules are player can move the queen towards the lower left corner of the grid: south, west, or southwest, any number of steps. The winner is the player who moves the queen into the southwest corner.If you let the old Xiao Ren first chess .Suppose they will use the best strategy who will win the game?

输入描述:

The input will consist of a series of pairs of integers a and b, Indicates the distance from the west boundary and the distance from the south boundary.

输出描述:

For each pair of input integers a and b you should output the winner's name in one line;

输入

1 2
3 5
1 1
3 2

输出

Lao Wang
Lao Wang
Xiao Ren
Xiao Ren

image.png

题意

给定一个大小为10000*10000的棋盘,给出皇后(queen)与棋盘左,下的距离。Lao Wang和Xiao Ren轮流执行操作:向左、下、左下移动任意步,Xiao Ren先手,先将皇后(queen)移至左下角的人获胜。请判断谁能获胜?

分析

打表sg函数可以很容易发现先手必败局势为(1,2),(3,5),(4,7)...可以看出来是威佐夫博弈(实际上向左边移动等价于取第一堆石子,向下移动等价于取第二堆石子,向左下移动等价于两堆同时取相同数目的石子),满足关系 a=floor((b-a)*1.618)(floor表示向下取整,没找到向下取整符号),差值比为黄金分割比。

题解

#include<bits/stdc++.h>
using namespace std; 
const double Gsr=(1+sqrt(5.0))/2; 
int main(){
    int a;
    int b;
    while(~scanf("%d%d",&a,&b)){
        if(a>b)  
        {  
            swap(a,b);  
        }  
        if(a == (int)(Gsr*(b-a))) 
            puts("Lao Wang");  
        else  
            puts("Xiao Ren"); 
    }

    return 0;
}

image.png