[CQOI2013]棋盘游戏

最终是没有平局的。

我们发现白方赢是只有一步吃掉黑方。

所以有人用dfs dp 过的。

我是用贝贝的方法做的。

http://tieba.baidu.com/p/2354159387

(我写的有些繁琐)

/**
 * Problem:chess
 * Author:Shun Yao
 * Time:2013.5.27
 * Result:Accepted
 * Memo:DP
 */

#include <cstring>
#include <cstdlib>
#include <cstdio>

#define MaxN (20)
#define MaxS (320000)
#define ai(a, b, c, d, e) (((((b) * MaxN + (c)) * MaxN + (d)) * MaxN + (e)) * 2 + (a))

void ia(long x, long &i, long &j, long &k, long &l, long &m) {
	m = x % 2;
	x >>= 1;
	l = x % MaxN;
	x /= MaxN;
	k = x % MaxN;
	x /= MaxN;
	j = x % MaxN;
	x /= MaxN;
	i = x % MaxN;
}

const long di[8] = {1, -1, 0, 0, 2, -2, 0, 0};
const long dj[8] = {0, 0, 1, -1, 0, 0, 2, -2};

long n, f[MaxS], g[MaxS];

bool Modify(long m, long i, long j, long k, long l, long Y) {
	if (i == k && j == l)
		return false;
	if (!m) {
		long ff = 0, gg = 0;
		for (long x = 0; x < 4; ++x) {
			long ii = i + di[x], jj = j + dj[x];
			if (ii < 0 || ii >= n || jj < 0 || jj >= n)
				continue;
			long y = ai(1, ii, jj, k, l);
			if (f[y] == 0) {
				if (ff == 0) {
					ff = 1;
					gg = g[y];
				} else if (gg > g[y])
					gg = g[y];
			} else if (!ff && f[y] == 1) {
				if (gg < g[y])
					gg = g[y];
			}
		}
		if (f[Y] != ff || g[Y] != gg + 1) {
			f[Y] = ff;
			g[Y] = gg + 1;
			return true;
		}
	} else {
		long ff = 0, gg = 0;
		for (long x = 0; x < 8; ++x) {
			long ii = k + di[x], jj = l + dj[x];
			if (ii < 0 || ii >= n || jj < 0 || jj >= n)
				continue;
			long y = ai(0, i, j, ii, jj);
			if (f[y] == 0) {
				if (ff == 0) {
					ff = 1;
					gg = g[y];
				} else if (gg > g[y])
					gg = g[y];
			} else if (!ff && f[y] == 1) {
				if (gg < g[y])
					gg = g[y];
			}
		}
		if (f[Y] != ff || g[Y] != gg + 1) {
			f[Y] = ff;
			g[Y] = gg + 1;
			return true;
		}
	}
	return false;
}

long Q[MaxS + 1], *L = Q, *R = Q;
char inq[MaxS];

int main() {
	freopen("chess.in", "r", stdin);
	freopen("chess.out", "w", stdout);
	scanf("%ld", &n);
	memset(f, 0, sizeof f);
	memset(g, 0, sizeof g);
	memset(inq, 0, sizeof inq);
	for (long i = 0; i < n; ++i)
		for (long j = 0; j < n; ++j) {
			long aa = ai(0, i, j, i, j);
			f[aa] = f[aa + 1] = 0;
			g[aa] = g[aa + 1] = 0;
			inq[*(R++) = aa] = 1;
			inq[*(R++) = aa + 1] = 1;
		}
	long i, j, k, l, m;
	while (L != R) {
		inq[*L] = 0;
		if (g[*L] == 0x7f7f7f7f) {
			++L;
			if (L > Q + MaxS)
				L = Q;
			continue;
		}
		ia(*L, i, j, k, l, m);
		if (m == 1) {
			for (long x = 0; x < 4; ++x) {
				long ii = i + di[x], jj = j + dj[x];
				if (ii < 0 || ii >= n || jj < 0 || jj >= n)
					continue;
				long y = ai(0, ii, jj, k, l);
				if (Modify(0, ii, jj, k, l, y) && !inq[y]) {
					inq[*(R++) = y] = 1;
					if (R > Q + MaxS)
						R = Q;
				}
			}
		} else {
			for (long x = 0; x < 8; ++x) {
				long ii = k + di[x], jj = l + dj[x];
				if (ii < 0 || ii >= n || jj < 0 || jj >= n)
					continue;
				long y = ai(1, i, j, ii, jj);
				if (Modify(1, i, j, ii, jj, y) && !inq[y]) {
					inq[*(R++) = y] = 1;
					if (R > Q + MaxS)
						R = Q;
				}
			}
		}
		++L;
		if (L > Q + MaxS)
			L = Q;
	}
	scanf("%ld%ld%ld%ld", &i, &j, &k, &l);
	i = ai(0, i - 1, j - 1, k - 1, l - 1);
	if (f[i] == 1)
		printf("WHITE ");
	else
		printf("BLACK ");
	printf("%ld", g[i]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/hsuppr/p/3103940.html