列表

详情


NC221008. 拱桥(Hard Version)

描述

本题有Easy,Hard两个版本,两个版本之间的区别仅在数据范围,通过Hard Version的代码可以直接通过Easy Version。保证Easy Version的测试用例集是Hard Version的子集


现在有一个(n行m列,最左上角的坐标为1,1)的棋盘,你要在上面修建一些拱桥。
众所周知,修建一座拱桥需要两个桥墩,我们规定两个桥墩之间的欧几里得距离应该在之间。
棋盘上面恰好有一个格子是坏掉的,你不能在坏掉的格子上面修建任何桥墩(但是允许有拱桥跨过此格)
你只能将桥墩修建在格子的正中心,且每个格子只能修建唯一的一个桥墩。
你并不需要担心修建的桥之间由于交叉导致冲突的问题,实际上,你可以通过修建不同高度的桥来避免它们冲突。

你想要尽可能多的在棋盘上面修建拱桥,请你给出一个修建拱桥数目最多的方案。

输入描述

首先输入一个正整数表示有T组测试案例,对于每组测试案例:
第一行输入两个正整数表示棋盘的大小是n行m列。

第二行输入一个坐标

输入数据保证

输出描述

对于每组测试案例:
输出n行,每行m个数字。每个坐标上的数字表示桥墩属于哪一座桥,一座桥有两个桥墩。
你可以用俩个相同的正整数表示一座桥,注意同一座桥的两个桥墩之间的欧几里得距离应该在之间。
如果某个格子上没有桥墩,则在该位置输出“-1”。

请保证坐标上的数字为“-1”。

示例1

输入:

1
3 3
2 2

输出:

1 2 3
3 -1 1
4 2 4

说明:

构造方案如题面上的图片所示。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 240ms, 内存消耗: 97112K, 提交时间: 2021-10-15 21:58:10

#include<bits/stdc++.h>
#define L(i, j, k) for (int i = (j); i <= (k); ++i) 
#define R(i, j, k) for (int i = (j); i >= (k); --i)  
#define ll long long
#define vi vector < int > 
#define sz(a) ((int) (a).size())
using namespace std;
const int N = 1e6 + 7;
int n, m, nowc, px, py, mat[N], tp, a[N], vis[N], rtp;
vi e[N];
mt19937 orz(time(0) ^ clock());
bool dfs (int x) {
	vis[x] = rtp;
	for (const int &v : e[x]) {
		int f = mat[v];
		if (vis[f] == rtp) continue;
		mat[x] = v, mat[v] = x, mat[f] = false;
		if (!f || dfs (f)) return true;
		mat[v] = f, mat[f] = v, mat[x] = false;
	}
	return 0;
}
bool iP (int x, int y) {
	return x == px && y == py;
}
vi id[N];
int top;
void Main () {
//	n = 4, m = 100, px = 1, py = 1;
	cin >> n >> m >> px >> py; 
	L(i, 0, n * m) a[i] = -1, mat[i] = 0;
	L(i, 1, n) id[i].resize(m + 1);
	top = 0;
	int rt = 0, ln = 1, rn = n, lm = 1, rm = m;
	while (px - ln >= 10) {
		L(i, ln, ln + 1) L(j, lm, rm) ++top, e[top].clear(), id[i][j] = id[i + 2][j] = top, a[top] = ++rt;
		ln += 4;
	}
	while (rn - px >= 10) {
		rn -= 4;
		L(i, rn + 1, rn + 2) L(j, lm, rm) ++top, e[top].clear(), id[i][j] = id[i + 2][j] = top, a[top] = ++rt;
	}
	
	while (py - lm >= 10) {
		L(i, ln, rn) L(j, lm, lm + 1) ++top, e[top].clear(), id[i][j] = id[i][j + 2] = top, a[top] = ++rt;
		lm += 4;
	}
	
	while (rm - py >= 10) {
		rm -= 4;
		L(i, ln, rn) L(j, rm + 1, rm + 2) ++top, e[top].clear(), id[i][j] = id[i][j + 2] = top, a[top] = ++rt;
	}
	
	L(i, 1, n) L(j, 1, m) 
		if((ln <= i && i <= rn) && (lm <= j && j <= rm) && !iP(i, j)) id[i][j] = ++top, e[top].clear ();	
	id[px][py] = 0;
	
	L(i, 1, n) L(j, 1, m) if((ln <= i && i <= rn) && (lm <= j && j <= rm) && !iP(i, j)) L(wi, max(i - 2, 1), min(i + 2, n)) 
		L(wj, max(j - 2, 1), min(j + 2, m)) 
		if((ln <= wi && wi <= rn) && (lm <= wj && wj <= rm) && !iP(wi, wj)) {
			int cnt = (abs(wi - i) == 2) + (abs(wj - j) == 2) ;
			if(cnt == 1) e[id[i][j]].push_back(id[wi][wj]); 
		} 
	
	
	vi cur (top);
	L(i, 0, top - 1) cur[i] = i + 1;
	shuffle(cur.begin(), cur.end(), orz);
	for (const int &x : cur) if (!mat[x]) ++rtp, dfs (x);
	
	L(i, 1, top) if(i < mat[i]) a[i] = a[mat[i]] = ++rt;
	L(i, 1, n) L(j, 1, m) cout << a[id[i][j]] << " \n"[j == m];
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int T = 1;
	cin >> T;
	while (T--) Main ();
	return 0;
}

上一题