1. 程式人生 > >BZOJ3298: [USACO 2011Open]cow checkers(佐威夫博弈)

BZOJ3298: [USACO 2011Open]cow checkers(佐威夫博弈)

3298: [USACO 2011Open]cow checkers

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 195  Solved: 96
[Submit][Status][Discuss]

Description

一天,Besssie準備和FJ挑戰奶牛跳棋遊戲。這個遊戲上在一個M*N的棋盤上, 這個棋盤上在(x,y)(0<=x棋盤的左下角是(0,0)座標,棋盤的右上角是座標(M-1,N-1)。 Bessie每次都是第一個移動棋子,然後Bessie與Fj輪流移動。每一輪可以做以下三種中的一種操作: 1)在同一行,將棋子從當前位置向左移動任意格; 2)在同一列,將棋子從當前位置向下移動任意格; 3)將棋子從當前位置向下移動k格再向左移動k格(k為正整數,且要滿足移動後的棋子仍然在棋盤上) 第一個不能在棋盤上移動的人比賽算輸(因為棋子處在(0,0)點)。 共有T個回合(1<=T<=1,000),每次給出一個新起始點的座標(x,y),確定是誰贏。 1<=M<=1,000,000;1<=N<=1,000,000

Input

第1行:兩個用空格隔開的整數M和N;   第2行:一個整數T;   第3到第T+2行:兩個用空格隔開的整數x和y. 

Output

第1到T行:包含“Farmer John”或者是“Bessie”,表示誰贏了這輪遊戲。

Sample Input

3 3
1
1 1

Sample Output

Bessie

HINT

Source

Silver

 

思路:開始看到通過的人少,沒想到就是一個裸的博弈。

開始我是這樣想的,對於每一行,每一列,都至多有一個必敗態。我們可以先打表求出早規律。

先有(0,0)為必敗態,然後標記這一行,這一列,以及這個對角線。 然後輸出的就是 (0,0) (2,1)( 5,3) (7,4)....

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int lose[maxn],x[maxn],y[maxn],d[maxn];
void solve(int N)
{
    y[0]=1; d[0]=1;
    for(int i=1;i<=N;i++){
        for(int j=1;j<i;j++){
            
if(!y[j]&&!d[i-j]&&!x[j]){ cout<<i<<" "<<j<<endl; x[i]=1; y[j]=1; d[i-j]=1; break; } } } } int main() { int T,N,M,x,y; solve(100); return 0; }
View Code

這不就是兩堆石子,可以取任一堆任意個,或者兩堆取一樣多的模型嗎。。。。失了智了。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T,N,M,x,y;
    scanf("%d%d%d",&N,&M,&T);
    while(T--){
        scanf("%d%d",&x,&y);
        if(x>y) swap(x,y); int z=y-x;
        if((int)((double)1.0*z*((double)1.0*(sqrt(5.0)+1)/2))==x) puts("Farmer John");
        else puts("Bessie");
    }
    return 0;
}