首页 > 代码库 > ZOJ 3810 A Volcanic Island

ZOJ 3810 A Volcanic Island

题意:

n*n的格子  将它分成n份大小为n的连通块  要求每个块形状不同  用4种颜色将格子染色后输出

思路:

纯构造题  考验智商  不过还是有思路可寻的

首先这题要想到将格子分区域的去做(想不到就没办法了…)假设我们两行为一个区域  那么将这两行划分成两个面积为n的块之后发现它们的形状必然相同  因此两行不行  所以我们尝试3行为1个区域!!  可以构造:

这样构造就可以保证形状不同  但是绿色会连上!!  那么我们通过奇偶性将图翻转  这样绿色就不会连上了  因为连起来至少需要绿色的外边长为n/2  但我们是3列分1个区域  也就是说绿色外边长最大就是n/3

还有问题  因为n不见得正好被3整除  不整除的时候如果余1就好办(直接加一行纯色的)  余2就麻烦了

如果余2  那么我们需要拆掉上图中的第一个(也就是构造时候绿色边长从2开始)  这时我们共有5行  填一行纯色的  还剩4行  接下来按这样构造:

根据上述构造方法  在n整除3的时候还会出现问题  因为图1中绿色的部分可能变成矩形  导致红色和蓝色形状相同  这时候只要把红色和蓝色其中一个格子换一下就好了  换的方法有很多(只要这两个不对称就行)

还有要注意特判1和5的时候直接构造一个答案输出  2、3、4时候没答案

代码:

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long LL;
#define N 110
#define M 400010
#define inf 2147483647
#define lowbit(x) (x&(-x))

char f[N][N]; //RBYG

int main() {
	int t, n, i, j, k, flag;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		if (n == 1)
			puts("R");
		else if (n < 5)
			puts("No solution!");
		else if (n == 5) {
			puts("YYYGR");
			puts("YGGGR");
			puts("YGYYR");
			puts("BYYYR");
			puts("BBBBR");
		} else {
			flag = n / 3;
			for (k = n; k > 5; k -= 3, flag--) {
				for (i = k; i > k - 3; i--) {
					for (j = 1; j <= n; j++)
						f[i][j] = 'R';
				}
				if (flag & 1) {
					for (i = k; i > k - 3; i--) {
						for (j = n - flag + 1; j <= n; j++)
							f[i][j] = 'Y';
					}
					for (j = flag * 2 + 1; j <= n; j++)
						f[k - 1][j] = 'Y';
					for (j = flag + 1; j <= flag + flag; j++)
						f[k - 1][j] = 'B';
					for (j = 1; j <= n - flag; j++)
						f[k][j] = 'B';
				} else {
					for (i = k; i > k - 3; i--) {
						for (j = 1; j <= flag; j++)
							f[i][j] = 'Y';
					}
					for (j = 1; j <= n - flag * 2; j++)
						f[k - 1][j] = 'Y';
					for (j = n - flag - flag + 1; j <= n - flag; j++)
						f[k - 1][j] = 'B';
					for (j = flag + 1; j <= n; j++)
						f[k][j] = 'B';
				}
			}
			if (k > 3) {
				for (j = 1; j <= n; j++)
					f[k][j] = 'G';
				k--;
			}
			if (k > 3) {
				for (i = 1; i <= 4; i++) {
					for (j = 1; j <= n; j++)
						f[i][j] = 'G';
				}
				for (i = 1; i <= 4; i++)
					f[i][1] = 'R';
				for (j = 2; j <= n - 3; j++)
					f[4][j] = 'R';
				f[4][n - 2] = f[4][n - 1] = f[4][n] = 'B';
				for (j = 2; j <= n - 2; j++)
					f[3][j] = 'B';
				f[3][n - 1] = f[3][n] = 'Y';
				for (j = 2; j <= n - 1; j++)
					f[2][j] = 'Y';
			} else {
				for (i = 1; i <= 3; i++) {
					for (j = 1; j <= n; j++)
						f[i][j] = 'Y';
				}
				for (j = 1; j <= n - 1; j++)
					f[1][j] = 'R';
				f[2][1] = 'R';
				for (j = 1; j <= n - 1; j++)
					f[3][j] = 'B';
				f[2][2] = 'B';
			}
			if (n % 3 == 0) {
				flag = n / 3;
				if (flag & 1)
					swap(f[n - 1][1], f[n - 1][flag + 1]);
				else
					swap(f[n - 1][n - flag], f[n - 1][n]);
			}
			for (i = 1; i <= n; i++) {
				for (j = 1; j <= n; j++)
					putchar(f[i][j]);
				putchar('\n');
			}
		}
	}
	return 0;
}


ZOJ 3810 A Volcanic Island