HDU 5754 Life Winner Bo (各种博弈融合)

题目链接:HDU 5754


题面:

Life Winner Bo

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 827    Accepted Submission(s): 309


Problem Description
Bo is a "Life Winner".He likes playing chessboard games with his girlfriend G.

The size of the chessboard is N×M .The top left corner is numbered (1,1) and the lower right corner is numberd (N,M) .

For each game,Bo and G take turns moving a chesspiece(Bo first).At first,the chesspiece is located at (1,1) .And the winner is the person who first moves the chesspiece to (N,M) .At one point,if the chess can't be moved and it isn't located at (N,M) ,they end in a draw.

In general,the chesspiece can only be moved right or down.Formally,suppose it is located at (x,y) ,it can be moved to the next point (x,y) only if xx and yy .Also it can't be moved to the outside of chessboard.

Besides,There are four kinds of chess(They have movement rules respectively).

1.king.

2.rook(castle).

3.knight.

4.queen.

(The movement rule is as same as the chess.)

For each type of chess,you should find out that who will win the game if they both play in an optimal strategy.

Print the winner's name("B" or "G") or "D" if nobody wins the game.
 

Input
In the first line,there is a number T as a case number.

In the next T lines,there are three numbers type, N and M .

"type" means the kind of the chess.

T1000,2N,M1000,1type4
 

Output
For each question,print the answer.
 

Sample Input
  
  
4 1 5 5 2 5 5 3 5 5 4 5 5
 

Sample Output
  
  
G G D B
 

Source


题意:

     给定N*M的棋盘,一共4颗棋子,每次一种1颗棋子,从左上角出发,到右下角的人获胜。


解题:

    1.王的走法是向下向右1格,或同时向下向右1格,即(x+1,y)/(x,y+1)/)(x+1,y+1)三种走法,递推推一下即可。一个节点的后继为必败态,那么它为必胜态,如果一个节点的后继全都是必胜态,那么它就是必败态,按剩余步数,从小到大递推一下即可。

     2.车的走法是横向或竖向任意格,那么在对角线上必输,因为先手走什么策略,后手模仿即可,反之n!=m,先手只要使对方到对角线上即必胜。

     3.马的走法和中国象棋是一样的,日字形,马比较特殊的是,会出现平局的情况,即谁都不能到达(n,m),马的递推是,如果后继中有必败态,那么当前节点是必胜态,如果后继中都是必胜态,那么当前节点是必败态,如果后继中有平局,那么当前节点即为平局。(以上推导严格有序,即在排除了前一种情况的前提下成立)。

    4.皇后的走法和王类似,不过王后是走任意步,或者沿斜线任意步。这其实可以看成,两堆石子,要么从一堆取任意个,要么从两堆同时取相同任意个。这就是威佐夫博弈,可见这篇博客

     这题综合考察了几种博弈,还是很不错的,没有接触过博弈的人,可以学到很多。


代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#define LL long long
using namespace std;
bool king[1005][1005];
int horse[1005][1005];
bool vis[1005][1005];
int main()
{
	int t,type,n,m,s1,s2;
	memset(king,0,sizeof(king));
	king[0][0]=0;
	for(int i=0;i<=1000;i++)
	{
		for(int j=0;j<=1000;j++)
		{
			if(king[i][j]==0)
			{
				if(i+1<=1000)
				    king[i+1][j]=1;
				if(j+1<=1000)
					king[i][j+1]=1;
                if(i+1<=1000&&j+1<=1000)
					king[i+1][j+1]=1;
			}
		}
	}
    memset(horse,-1,sizeof(horse));
	horse[0][0]=0;
	for(int i=0;i<=1000;i++)
	{
		for(int j=0;j<=1000;j++)
		{
			s1=-2;s2=-2;
		   if(i-1>=0&&j-2>=0)
              s1=horse[i-1][j-2];
		   if(i-2>=0&&j-1>=0)
			  s2=horse[i-2][j-1];
           if(s1!=-2&&s2!=-2)
		   {
			   if(s1==0||s2==0)
				   horse[i][j]=1;
			   else if(s1==-1||s2==-1)
				   horse[i][j]=-1;
			   else
				   horse[i][j]=0;
		   }
		   if(s1!=-2||s2!=-2)
		   {
			   if(s1==0||s2==0)
				   horse[i][j]=1;
			   else if(s1==-1||s2==-1)
				   horse[i][j]=-1;
			   else
				   horse[i][j]=0;
		   }
		  
		}
	}
	scanf("%d",&t);
    while(t--)
	{
		int flag;
		scanf("%d%d%d",&type,&n,&m);
		if(type==1)
		{
			if(king[n-1][m-1]==1)
				flag=1;
			else
				flag=0;
		}
		else if(type==2)
		{
			if(n==m)
				flag=0;
			else
				flag=1;
		}
		else if(type==3)
		{
			n--;
			m--;
			if(horse[n][m]==-1)
				flag=2;
			else if(horse[n][m])
				flag=1;
			else
				flag=0;
		}
		else
		{
			int dif,tmp;
			n--;
			m--;
			if(n>m)
				swap(n,m);
		    dif=m-n;
			tmp=dif*(1.0+sqrt(5.0))/2;
			if(n==tmp)
				flag=0;
			else
				flag=1;
		}
		if(flag==2)
			printf("D\n");
		else if(flag==1)
			printf("B\n");
		else
			printf("G\n");
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值