CSU 1013: 狐狸与小狗

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nameofcsdn/article/details/79958309

题目:

Description

Upwinder最近喜欢上了一款古老的起源于Scandinavia(斯堪迪纳维亚半岛)的小游戏。具体的游戏规则如下:

1. 棋盘设定

棋盘的大小为8行8列,有两个玩家:狐狸和小狗。初始的时候有4只小狗被放置在棋盘最上边一行的4个黑色格子里;而1只狐狸被放在最下边一行的某个黑色格子里。以棋盘左上角为原点,向下为行的正方向,向右为列的正方向,从1开始给每一个格子编号,如图1所示。

fox_and_dog

2. 移动规则

(1) 两个玩家轮流下棋。

(2) 狐狸每轮可以斜着向上或斜着向下移动至相邻的一个空格子,只能移动一步;

(3) 小狗每轮只能斜着向下移动至相邻的一个空格子,只能移动一只,且只能移动一步;

(4) 显然根据移动规则棋盘中只有黑色的格子才能放棋子

3. 游戏目标

狐狸与小狗的目标是不同的。

(1) 如果小狗将狐狸围住致使其无法移动(包括围在边界),那么小狗获胜(参考图2-A,B,C)。

fox_and_dog-2

(2) 如果狐狸到达了棋盘最上方一行的任意一个黑色格子,那么狐狸获胜(参考图2-D);

特别的,游戏不存在平局或死局,而且如果4只小狗均无法移动,则狐狸可以一直移动直至取胜。

现在告诉你游戏过程中的某一个局面,你能帮Upwinder判断如果狐狸与小狗均采取最优策略的话,谁能取得最后的胜利吗?

Input

第一行一个数字T表示接下来有T(T<=3000)种局面。

对于每一种局面,由三行数据组成,其中:

第一行为整数0或1。0代表当前狐狸掌握棋权,1代表当前小狗掌握棋权。

第二行为两个整数,以空格分隔,依次是狐狸在棋盘上的行坐标Fr和列坐标Fl。

第三行为八个整数,以空格分隔,依次是第一只小狗的行坐标Dr1,列坐标Dl1……以此类推。

Output

对于每一种局面,仅输出一行。

如果狐狸能够取胜,请输出“Fox win”(不含引号)

如果小狗能够取胜,请输出“Dog win”(不含引号)

Sample Input

4
0
4 4
3 3 3 5 5 3 5 5
1
1 3
3 1 2 4 3 5 4 4
0
5 3
3 3 3 5 3 7 2 8
1
7 7
6 4 5 5 4 6 4 8

Sample Output

Dog win
Fox win
Fox win
Dog win


思路:

首先对32个格子编号,0-31

4个狗的编号为b1,b2,b3,b4,狐狸的编号为c

每次都保持b1<b2<b3<b4,这样所有节点的个数大约是2*32*32*32*32*32/24,大约200万,刚好不会超时

其次是胜负判断,如果c<b1那么狐狸赢,否则就一直继续,直到谁没法移动了谁就输了

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

char ans[2][32][32][32][32][32];
//轮到谁下,4个狗的位置,1个狐狸的位置

int gleft(int k)//左孩子
{
	int i = k / 4 + 1, j = k % 4 - i % 2;
	if (j < 0)return 32;
	return i * 4 + j;
}

int gright(int k)//右孩子
{
	int i = k / 4, j = k % 4 + i % 2;
	if (j >= 4)return 32;
	return ++i * 4 + j;
}

int hu(int k,int d)
{
	int i = k / 4, j = k % 4;
	if (d == 1)--i, j -= i % 2;
	if (d == 2)j += i % 2, i--;
	if (d == 3)++i, j -= i % 2;
	if (d == 4)j += i % 2, i++;
	if (i < 0 || i >= 8 || j < 0 || j >= 4)return 32;
	return i * 4 + j;
}

char f(int a, int b1, int b2, int b3, int b4, int c)
{
	if (b1 == b2 || b1 == b3 || b1 == b4 || b1 == c)return 'F';
	if (b1 >= 32 || b2 >= 32 || b3 >= 32 || b4 >= 32)return 'F';
	if (c >= 32)return 'D';
	if (b1 > b2)b1 ^= b2 ^= b1 ^= b2;
	if (b2 > b3)b2 ^= b3 ^= b2 ^= b3;
	if (b3 > b4)b3 ^= b4 ^= b3 ^= b4;
	if (c < b1)return 'F';
	if (ans[a][b1][b2][b3][b4][c] !='0')
		return ans[a][b1][b2][b3][b4][c];
	if (a)
	{
		if (f(1 - a, gleft(b1), b2, b3, b4, c) == 'D' ||
			f(1 - a, gright(b1), b2, b3, b4, c) == 'D' ||
			f(1 - a, gleft(b2), b1, b3, b4, c) == 'D' ||
			f(1 - a, gright(b2), b1, b3, b4, c) == 'D' ||
			f(1 - a, gleft(b3), b1, b2, b4, c) == 'D' ||
			f(1 - a, gright(b3), b1, b2, b4, c) == 'D' ||
			f(1 - a, gleft(b4), b1, b2, b3, c) == 'D' ||
			f(1 - a, gright(b4), b1, b2, b3, c) == 'D')
			ans[a][b1][b2][b3][b4][c] = 'D';
		else ans[a][b1][b2][b3][b4][c] = 'F';
	}
	else
	{
		int k;
		ans[a][b1][b2][b3][b4][c] = 'D';
		for (int i = 1; i <= 4; i++)
		{
			k = hu(c, i);
			if (b1 == k || b2 == k || b3 == k || b4 == k)continue;
			if (f(1 - a, b1, b2, b3, b4, k) == 'F')ans[a][b1][b2][b3][b4][c] = 'F';
		}
	}
	return ans[a][b1][b2][b3][b4][c];
}

int main()
{
	memset(ans, '0', sizeof(ans));
	int t, a, x[5], y;
	cin >> t;
	while (t--)
	{
		cin >> a;
		for (int i = 0; i < 5; i++)
		{
			cin >> x[i] >> y;
			x[i] = --x[i] * 4 + --y / 2;
		}
		sort(x + 1, x + 5);
		char r = f(a, x[1], x[2], x[3], x[4], x[0]);
		if (r == 'D')cout << "Dog win\n";
		else cout << "Fox win\n";
	}
	return 0;
}

阅读更多

没有更多推荐了,返回首页