CodeForces - 297D Color the Carpet

Description

\(n\times m\) 的棋盘,用 \(K\) 种颜色给每个格子染色,并给出每两个相邻格子间的要求(相同或不同),构造一种方案使得至少满足其中 \(\cfrac{3}{4}\) 的要求。

\(n,m\le 1000\)

Solution

这出题人怎么不出 5000

我会构造.jpg

结论是无解的情况存在且仅存在于 \(K=1\)\(N\) 的数量大于 \(\cfrac{tot}{4}\) 时。别的情况一定可以用两个颜色构造出解。接下来是构造方法和证明。

假定竖着的要求数量大于横着的(不是的话可以转一下),那先不考虑横着的要求,那对于每一列一定可以用至多两种颜色构造出完全符合该列所有要求的方案。于是这样就满足了总要求的 \(\cfrac{1}{2}\)

然后考虑横着的要求。枚举每一列,若当前列与上一列间的横着的要求中,不成立的大于 \(\cfrac{1}{2}\) ,那就把当前列全部取反。于是最后横要求也能满足 \(\cfrac{1}{2}\) ,总共就能满足 \(\cfrac 3 4\)

复杂度 \(O(nm)\)

#include<bits/stdc++.h>
using namespace std;

template <class T> void read(T &x) {
	x = 0; bool flag = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) flag |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; flag ? (x = -x) : 0;
}

#define N 1010
#define rep(i, a, b) for (int i = (a); i <= (b); i++)

int n, m, K, r1, r2, c1, c2, ans[N][N];
bool r[N][N], c[N][N], tmp[N][N];

int main() {
	read(n), read(m), read(K);
	r2 = m, c2 = m - 1;
	int nCnt = 0, tot = 0;
	rep(i, 1, 2 * n - 1) {
		int x = (i & 1) ? m - 1 : m;
		(x == m ? r1 : c1)++;
		rep(j, 1, x) {
			char ch = getchar(); for (; ch != 'E' && ch != 'N'; ch = getchar());
			nCnt += (ch == 'N'), tot++;
			(x == m - 1 ? c[c1][j] : r[r1][j]) = (ch == 'E');
		}
	}

	if (K == 1) {
		if (nCnt <= tot / 4) {
			puts("YES");
			rep(i, 1, n) {
				rep(j, 1, m) printf("1 ");
				puts("");
			}
		}
		else puts("NO");
		return 0;
	}

	bool swapTag = 0;
	if (r1 * r2 < c1 * c2) {
		swapTag = 1;
		memcpy(tmp, r, sizeof r), memset(r, 0, sizeof r);
		rep(i, 1, c1) rep(j, 1, c2) r[j][i] = c[i][j];
		memset(c, 0, sizeof c);
		rep(i, 1, r1) rep(j, 1, r2) c[j][i] = tmp[i][j];
		swap(n, m), r1 = n - 1, r2 = m, c1 = n, c2 = m - 1;
	}

	rep(j, 1, m) rep(i, 2, n) ans[i][j] = ans[i - 1][j] ^ (r[i - 1][j] ? 0 : 1);
	rep(j, 2, m) {
		int cnt = 0;
		rep(i, 1, n) cnt += (c[i][j - 1] != (ans[i][j] == ans[i][j - 1]));
		if (cnt > n / 2) rep(i, 1, n) ans[i][j] = ans[i][j] ^ 1;
	}

	puts("YES");
	if (swapTag) {
		rep(i, 1, m) {
			rep(j, 1, n) printf("%d ", ans[j][i] + 1);
			puts("");
		}
	}
	else {
		rep(i, 1, n) {
			rep(j, 1, m) printf("%d ", ans[i][j] + 1);
			puts("");
		}
	}
	return 0;
}
posted @ 2018-08-17 16:08  aziint  阅读(141)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.