uoj#225[UR #15]奥林匹克五子棋 构造

Posted GXZlegend

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uoj#225[UR #15]奥林匹克五子棋 构造相关的知识,希望对你有一定的参考价值。

题目描述

两个人在 $n\\times m$ 的棋盘上下 $k$ 子棋,问:是否存在一种平局的情况?如果存在则输出一种可能的最终情况。

输入

第一行三个正整数 $n,m,k$ ,意义如前所述。

输出

如果双方不能打成平局,输出 $−1$ ;

否则输出 $n×m$ 行,第 $i$ 行两个整数 $x_i,y_i$ 表示第 $i$ 次落子的坐标为第 $x_i$ 行第 $y_i$ 列。黑子先行,所以 $i$ 为奇数时为黑方落子,$i$ 为偶数时白方落子。坐标需满足 $1≤x_i≤n,1≤y_i≤m$ 。

样例输入

4 4 3

样例输出

1 2
1 1
1 4
1 3
2 1
2 3
2 2
2 4
3 3
3 2
3 4
3 1
4 1
4 4
4 3
4 2


题解

构造

显然 $k=1$ 时无解。

$k=2$ 当且仅当 $\\text{min}(n,m)=1$ 时有解。因为若 $n>1,m>1$ ,对于一个 $2\\times 2$ 的部分一定无法避免两个连续。

当 $k\\ge 3$ 时,可以构造出如下的棋盘:

显然这其中包含连续的棋子数最多只有 $2$ 。

那么是否满足O与X相差不超过1呢?

容易发现只有 $n\\mod 4=2$ (此时第一列会多填两个O)且 $m$ 为奇数时不成立,这种情况下把棋盘向上平移一排(即第一列从上至下是OXXOOXXOO...XXOOX)即可。

时间复杂度 $O(nm)$

#include <cstdio>
int ax[125010] , ay[125010] , at , bx[125010] , by[125010] , bt;
int main()
{
	int n , m , k , i , j;
	scanf("%d%d%d" , &n , &m , &k);
	if(k == 1) puts("-1");
	else if(k == 2)
	{
		if(n > 1 && m > 1) puts("-1");
		else
			for(i = 1 ; i <= n ; i ++ )
				for(j = 1 ; j <= m ; j ++ )
					printf("%d %d\\n" , i , j);
	}
	else
	{
		if((n & 3) == 2 && m & 1)
		{
			for(i = 1 ; i <= n ; i ++ )
			{
				for(j = 1 ; j <= m ; j ++ )
				{
					if(((i & 3) > 1) == (j & 1)) ax[++at] = i , ay[at] = j;
					else bx[++bt] = i , by[bt] = j;
				}
			}
		}
		else
		{
			for(i = 1 ; i <= n ; i ++ )
			{
				for(j = 1 ; j <= m ; j ++ )
				{
					if(((i & 3) && ((i & 3) < 3)) == (j & 1)) ax[++at] = i , ay[at] = j;
					else bx[++bt] = i , by[bt] = j;
				}
			}
		}
		for(i = 1 ; i <= n * m ; i ++ )
		{
			if(i & 1) printf("%d %d\\n" , ax[at] , ay[at]) , at -- ;
			else printf("%d %d\\n" , bx[bt] , by[bt]) , bt -- ;
		}
	}
	return 0;
}

 

以上是关于uoj#225[UR #15]奥林匹克五子棋 构造的主要内容,如果未能解决你的问题,请参考以下文章

UOJ#21UR #1缩进优化

UOJ_21_UR #1缩进优化_数学

UOJ#22UR #1外星人(动态规划)

[UOJ#192]UR #14最强跳蚤

UOJ#50UR #3链式反应(分治FFT,动态规划)

UOJ UR#2树上GCD(缓存)