hdu 1564 Play a game

12 篇文章 0 订阅

Play a game

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 919    Accepted Submission(s): 741


Problem Description
New Year is Coming! 
ailyanlu is very happy today! and he is playing a chessboard game with 8600. 
The size of the chessboard is n*n. A stone is placed in a corner square. They play alternatively with 8600 having the first move. Each time, player is allowed to move the stone to an unvisited neighbor square horizontally or vertically. The one who can't make a move will lose the game. If both play perfectly, who will win the game?
 

Input
The input is a sequence of positive integers each in a separate line. 
The integers are between 1 and 10000, inclusive,(means 1 <= n <= 10000) indicating the size of the chessboard. The end of the input is indicated by a zero.
 

Output
Output the winner ("8600" or "ailyanlu") for each input line except the last zero. 
No other characters should be inserted in the output.
 

Sample Input
  
  
2 0
 

Sample Output
  
  
8600
打表能发现奇偶规律:
打表代码:
View Code 
 #include<stdio.h>
 #include<stdlib.h>
 int n ;
 int graph[1010][1010] ;
 int tab[4][2] = {-1,0,1,0,0,-1,0,1} ; 
 int dfs (int x, int y)
 {    
      int xx, yy, i, ans ;          
      for (i = 0 ; i < 4 ; i++)    
      {        
            xx = x + tab[i][0] ;       
            yy = y + tab[i][1] ;        
            if (xx < 0 || xx >= n) continue ;        
            if (yy < 0 || yy >= n) continue ;        
            if (graph[xx][yy]) continue ;        
            graph[xx][yy] = 1 ;        
            ans = dfs (xx, yy) ;        
            graph[xx][yy] = 0 ;        
            if (ans == 0) return 1 ; //如果下一点是必败点  那么该点一定是必胜点;   
      }    
      return 0 ;
 }
 int main ()
 {    
      graph[0][0] = 1 ;    
      for (n = 1 ; n <= 8 ; n++)        
      printf ("%d, %d\n", n, dfs (0,0)) ;
      system( "pause" ); 
      return 0;
 }

以下是别人的证明:

定义记号(1,1)表示x坐标为奇,y坐标为奇,(0,1)为x坐标为偶,y坐标为奇 ,(0,0)(1,0)类推。

先说明一下结论:

n是奇数,后手胜,n是偶数,先手胜。

以n为奇数为例,说明一下制胜策略。

那么5*5棋盘为例,可以表示为:

(1,1)(1,0)(1,1)(1,0)(1,1) 1,2,3,4,5

(0,1) (0,0) (0,1) (0,0) (0,1) 6,7,8,9,10

(1,1)(1,0)(1,1)(1,0)(1,1)

(0,1) (0,0) (0,1) (0,0) (0,1)

(1,1)(1,0)(1,1)(1,0)(1,1)

先手开始(1,1),走了一步之后,必为(1,0)或(0,1);

后手只需移动到(1,1)或(0,0)即可。

一共25个格子,起初(1,1)去掉一个。还有24个,所以对称点和不对称点各有12个。先手都是不对称点,后手都是对称点。

那么刚好应该后手放最后一个。

说道这,有个地方,聪明人可能看出来。有可能没到最后,后手就没办法走了。那么我们假设一下吧。

的确有这个可能 比如2-3-8-9-10-5-4 ,先手2,8,10,4,这样的确不行。(写到这里,卡了我20来分钟,发现以前的想法是错的,还好我又想出个办法如下:)

10是先手选的,那么5是后手选的,10后手不能变,但是后手可以不选择5,改选别的。这样子,会有两个永远都取不到。不影响奇偶性,前面的推断依然可用。

这样子,我们一开始玩。出现第一个不行的话,就选另一个,而且,这样一定会舍弃偶数个格子。

严格来说,应该这样。设最后一个是先手点,那么前一个是后手点,这个后手点如果能改变则改变,如果不能改,就往前推。这样子,一改就是成对的点。要么最后取不到,要么换个方向取,不管怎么样,通过这种更改的方法,对每一种先手方案,一定能够造出后手必胜策略出来的。(能改变的后手点总是取得到的,这是因为根据图的点类型的对称性)

想想这个思想就是试验——出错——改进并且一定能改好。这样一步一步,结果能构造出。

如果n是偶数的话,对称点和不对称点个数差一,不对称多一个,是先手点的。思路同上。


AC代码:
#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;
int main()
{
    int n;
    while(cin>>n,n)
    {
        if(n%2==0)
        cout<<"8600"<<endl;
        else
        cout<<"ailyanlu"<<endl;

    }
   return 0;

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值