2016 Multi-University Training Contest 3 1003 Life Winner Bo

题目链接:点击打开链接

题目大意:给你四种棋子和一个n*m的棋盘,从(1,1)走到(n,m)问输赢平

解题思路:分析每一种棋子:

对于国王来说,相当于是在两堆石子中取,每次只能从一堆中取一个或者两堆一起各取一个:

(0,0)为必败态

(1,1)就是必胜态

那么到(1,1)奇数步距离的就一定也是必败态,说以(1,x)(x为奇数一定是必败态)

(2,2)是必胜态因为他可以转化成(1,1)

于是我们分析(3,3),下一步只能是(3,2)或者(2,3)这些都是一步到(2,2)的于是(3,3)为必败态,

同上(3,x)(x为奇数一定是必败态)

推广所有(x,y)只要x和y都是奇数就是必败态。

对于城堡来说,相当于是在两堆石子中取,每次从一堆中取任意个(典型的NIM博弈),直接n|m判胜负。

对于骑士来说,这里有点麻烦,因为会出现平局的情况。

我们来考虑下必胜的情况(3,3)对于这个点对方不论怎么走你都能获胜,于是推广(6,6),(9,9)。。。。。。都可以,这些点为必胜点,

而这些点一步到的点为必败点,

剩下的为平局。

最后,对于王后来说,相当于是在两堆石子中取,每次只能从一堆中取任意个或者两堆一起取相同任意个:

典型的威佐夫博弈,判断小的值是否等于1.618*差值就好。

代码:

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
#include "bitset"
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3 + 50;
const int Mod = 1e9 + 7;
const double PI = acos(-1);
const double d1618 = (sqrt(5) + 1) / 2;
typedef long long ll;

const int KNIGHT = 3;
const int QUEEN = 4;
const int KING = 1;
const int ROOK = 2;
const int WIN = 1;
const int DRAW = 0;
const int LOSE = -1;
int t, n, m;
int sn, sm;
int main()
{
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%d %d %d", &t, &n, &m);
		sn = n - 1;
		sm = m - 1;
		int ret, tmp;
		if (t == KNIGHT) {
			if (sn == sm && sn % 3 == 0 && sm % 3 == 0) ret = LOSE;
			else {
				int tn = sn % 3, tm = sm % 3;
				if (tn>tm) swap(tn, tm);
				if (sn / 3 == sm / 3 && tn == 1 && tm == 2) ret = WIN;
				else ret = DRAW;
			}
			//ret=knight[sn][sm];
		}
		else if (t == KING) {
			if ((n & 1) && (m & 1)) tmp = 0;
			else tmp = 1;
			if (tmp == 0) ret = LOSE;
			else ret = WIN;
		}
		else if (t == ROOK) {
			tmp = sn^sm;
			if (tmp == 0) ret = LOSE;
			else ret = WIN;
		}
		else if (t == QUEEN) {
			if (sn>sm) swap(sn, sm);
			int nn = (sm - sn)*d1618;
			if (nn == sn) ret = LOSE;
			else ret = WIN;
		}
		if (ret == WIN) puts("B");
		else if (ret == LOSE) puts("G");
		else puts("D");
	}



	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值