結果
| 問題 | No.3744 XY Tiling |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-09-19 09:19:41 |
| 言語 | C++23 (gcc 15.3.0 + boost 1.92.0 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 7 ms / 2,000 ms |
| + 767µs | |
| コード長 | 7,516 bytes |
| 記録 | |
| コンパイル時間 | 2,585 ms |
| コンパイル使用メモリ | 360,344 KB |
| 実行使用メモリ | 9,996 KB |
| 最終ジャッジ日時 | 2026-09-19 13:30:45 |
| 合計ジャッジ時間 | 6,372 ms |
|
ジャッジサーバーID (参考情報) |
judge5_0 / judge4_0 |
(要ログイン)
| サブタスク | 配点 | 結果 |
|---|---|---|
| 部分点 | 60 % | AC * 19 |
| 満点 | 40 % | AC * 60 |
| 合計 | 5 * 100% = 500 点 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
// min(H,W) <= 5 の構成
vector<vector<int>> build_small(int h, int w, int &C) {
vector<vector<int>> a(h, vector<int>(w));
if (h == 1) {
C = w / 2 + 1;
// 1 2 2 3 3 4 4 5 ...
for (int j = 0; j < w; j++) {
a[0][j] = (j + 1) / 2 + 1;
}
}
else if (h == 2) {
C = 2;
for (int j = 0; j < w; j++) {
a[0][j] = 1;
a[1][j] = 2;
}
}
else if (h == 3) {
C = (w + 3) / 4 + 2; // ceil(w / 4) + 2
for (int j = 0; j < w; j++) {
a[0][j] = 1;
a[1][j] = 2;
}
int j = 0;
int c = 3;
// 2 c c 2
while (j + 4 <= w) {
a[2][j] = 2;
a[2][j + 1] = c;
a[2][j + 2] = c;
a[2][j + 3] = 2;
c++;
j += 4;
}
// w ≡ 2 (mod 4)
if (j < w) {
a[2][j] = 2;
a[2][j + 1] = c;
}
}
else if (h == 4) {
C = 3;
for (int j = 0; j < w; j++) {
a[0][j] = 1;
a[1][j] = 2;
a[2][j] = 2;
a[3][j] = 3;
}
}
else { // h == 5
if (w == 6) {
C = 3;
a = {
{3, 3, 3, 3, 3, 1},
{1, 1, 1, 1, 3, 1},
{1, 2, 1, 3, 3, 1},
{1, 2, 1, 1, 1, 1},
{1, 2, 2, 2, 2, 2},
};
}
else if (w == 8) {
C = 3;
a = {
{3, 3, 3, 3, 3, 3, 3, 1},
{1, 1, 1, 1, 1, 1, 3, 1},
{1, 2, 2, 1, 1, 3, 3, 1},
{1, 2, 1, 1, 1, 1, 1, 1},
{1, 2, 2, 2, 2, 2, 2, 2},
};
}
else {
C = 4;
for (int j = 0; j < w; j++) {
a[0][j] = 1;
a[1][j] = 2;
a[2][j] = (j % 2 == 0 ? 2 : 3);
a[3][j] = 3;
a[4][j] = 4;
}
}
}
return a;
}
// h,w >= 6 かつ w は偶数
vector<vector<int>> build_big(int h, int w, int &C) {
C = 3;
const int base6[6][6] = {
{1, 1, 1, 1, 1, 3},
{2, 2, 2, 2, 1, 3},
{2, 1, 1, 1, 1, 3},
{2, 1, 3, 3, 1, 3},
{2, 1, 3, 3, 3, 3},
{2, 1, 1, 1, 1, 1},
};
// まず 6 x w に拡張する。
// 4 列目と 5 列目の間に、
// 元の 4 列目と同じ色配置の列を追加する。
vector<vector<int>> base(6, vector<int>(w));
for (int i = 0; i < 6; i++) {
int p = 0;
for (int j = 0; j < 4; j++) {
base[i][p++] = base6[i][j];
}
for (int j = 0; j < w - 6; j++) {
base[i][p++] = base6[i][3];
}
base[i][p++] = base6[i][4];
base[i][p++] = base6[i][5];
}
// 高さを増やす際に挿入する行。
//
// 2 1 2 1 2 1 ... 1 3
//
// w は偶数なので、横に 2 マスずつ組める。
vector<int> mid(w);
for (int j = 0; j < w - 2; j++) {
mid[j] = (j % 2 == 0 ? 2 : 1);
}
mid[w - 2] = 1;
mid[w - 1] = 3;
vector<vector<int>> a;
a.push_back(base[0]);
a.push_back(base[1]);
for (int i = 0; i < h - 6; i++) {
a.push_back(mid);
}
for (int i = 2; i < 6; i++) {
a.push_back(base[i]);
}
return a;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int H, W;
cin >> H >> W;
int C;
vector<vector<int>> color;
// H <= 5 の特殊ケースは、短い方を H として構成する。
if (min(H, W) <= 5) {
bool transpose = (H > W);
int h = min(H, W);
int w = max(H, W);
auto a = build_small(h, w, C);
color.assign(H, vector<int>(W));
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
color[i][j] =
transpose ? a[j][i] : a[i][j];
}
}
}
// 両辺 6 以上
else {
// build_big では横幅を偶数にする。
// HW は偶数なので、W が奇数なら H は偶数。
bool transpose = (W % 2 == 1);
int h = transpose ? W : H;
int w = transpose ? H : W;
auto a = build_big(h, w, C);
color.assign(H, vector<int>(W));
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
color[i][j] =
transpose ? a[j][i] : a[i][j];
}
}
}
// ------------------------------------------------------------
// 以下、色の異なる隣接マスだけに辺を張り、
// 完全マッチングを求めてタイル配置を決める。
// ------------------------------------------------------------
int N = H * W;
vector<vector<int>> graph(N);
vector<int> left;
const int di[] = {1, -1, 0, 0};
const int dj[] = {0, 0, 1, -1};
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if ((i + j) % 2) continue;
int u = i * W + j;
left.push_back(u);
for (int d = 0; d < 4; d++) {
int ni = i + di[d];
int nj = j + dj[d];
if (ni < 0 || ni >= H ||
nj < 0 || nj >= W) {
continue;
}
if (color[i][j] == color[ni][nj]) {
continue;
}
graph[u].push_back(ni * W + nj);
}
}
}
// Hopcroft-Karp
vector<int> mate(N, -1);
vector<int> dist(N);
vector<int> ptr(N);
auto bfs = [&]() {
queue<int> q;
fill(dist.begin(), dist.end(), -1);
bool found = false;
for (int u : left) {
if (mate[u] == -1) {
dist[u] = 0;
q.push(u);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : graph[u]) {
int nu = mate[v];
if (nu == -1) {
found = true;
}
else if (dist[nu] == -1) {
dist[nu] = dist[u] + 1;
q.push(nu);
}
}
}
return found;
};
function<bool(int)> dfs = [&](int u) {
for (int &k = ptr[u];
k < (int)graph[u].size();
k++) {
int v = graph[u][k];
int nu = mate[v];
if (nu == -1 ||
(dist[nu] == dist[u] + 1 && dfs(nu))) {
mate[u] = v;
mate[v] = u;
return true;
}
}
dist[u] = -1;
return false;
};
int matched = 0;
while (bfs()) {
fill(ptr.begin(), ptr.end(), 0);
for (int u : left) {
if (mate[u] == -1 && dfs(u)) {
matched++;
}
}
}
assert(matched * 2 == N);
// 出力
cout << C << '\n';
for (int u : left) {
int v = mate[u];
int x1 = u / W;
int y1 = u % W;
int x2 = v / W;
int y2 = v % W;
cout
<< x1 + 1 << ' '
<< y1 + 1 << ' '
<< color[x1][y1] << ' '
<< x2 + 1 << ' '
<< y2 + 1 << ' '
<< color[x2][y2] << '\n';
}
}