CF1567F One-Four Overload
CF1567F One-Four Overload
我居然把这道 的题切了!!!
没有标记的格子只能选 或者 , 标记的格子必须是 的倍数.
比较显然的是, 标记的格子周围必须有且只能有偶数个 (包括 ) 未标记的格子, 否则无解.
接下来我们考虑构造一组解.
比较显然的是, 如果一个标记的格子周围只有两个未标记的格子, 那么一定是一个 一个 , 不管是 形还是 形.
如果有 个呢? 那么我们就把同一行的和同一列的填上相同的数. 为什么?
因为一对 形的未标记格子只可能对应一个标记的格子, 而一对 形的可能对应两个标记的格子, 所以我们只需要保证这 个未标记格子分别组成的两组 形合法就够了.
所以我们就判断一下, 如果这个标记的格子周围只有两个未标记的, 直接连边, 四个的话, 把四个 连起来, 注意, 是双向边.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define calc(i, j) (i - 1) * m + j
int read() {
int x = 0, f = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * f;
}
const int N = 505, M = 1e6 + 5;
int n, m;
int a[N][N], ans[N * N];
int tot, to[M], nxt[M], head[M];
char s[N][N];
void Add(int u, int v) {
to[++tot] = v, nxt[tot] = head[u], head[u] = tot;
to[++tot] = u, nxt[tot] = head[v], head[v] = tot;
}
bool Check(int i, int j, int k, int l) {
if (!a[i][j] && !a[k][l]) return true;
return false;
}
int Sum(int x, int y) {
int sum = 0;
if (!a[x - 1][y]) sum += ans[calc(x - 1, y)];
if (!a[x][y - 1]) sum += ans[calc(x, y - 1)];
if (!a[x][y + 1]) sum += ans[calc(x, y + 1)];
if (!a[x + 1][y]) sum += ans[calc(x + 1, y)];
return sum;
}
void DFS(int x, int fa) {
ans[x] = 5 - ans[fa];
for (int i = head[x]; i; i = nxt[i]) {
int y = to[i];
if (!ans[y]) DFS(y, x);
}
}
int main() {
n = read(), m = read(), ans[0] = 1;
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
for (int j = 1; j <= m; j++) a[i][j] = s[i][j] == 'X';
}
for (int i = 2; i < n; i++) {
for (int j = 2; j < m; j++) {
if (a[i][j]) { //判断无解
if (a[i - 1][j] + a[i][j - 1] + a[i][j + 1] + a[i + 1][j] & 1) {
printf("NO");
return 0;
}
if (Check(i - 1, j, i + 1, j) && !Check(i, j - 1, i, j + 1)) Add(calc(i - 1, j), calc(i + 1, j));
else if (!Check(i - 1, j, i + 1, j) && Check(i, j - 1, i, j + 1)) Add(calc(i, j - 1), calc(i, j + 1));
else {
if (Check(i - 1, j, i, j + 1)) Add(calc(i - 1, j), calc(i, j + 1));
if (Check(i, j + 1, i + 1, j)) Add(calc(i, j + 1), calc(i + 1, j));
if (Check(i + 1, j, i, j - 1)) Add(calc(i + 1, j), calc(i, j - 1));
if (Check(i, j - 1, i - 1, j)) Add(calc(i, j - 1), calc(i - 1, j));
}
}
}
}
for (int i = 1; i <= n; i++) { //染色
for (int j = 1; j <= m; j++) {
if (!ans[calc(i, j)] && !a[i][j]) DFS(calc(i, j), 0);
}
}
for (int i = 1; i <= n; i++) { //统计 marked cell 的答案
for (int j = 1; j <= m; j++) {
if (a[i][j]) {
ans[calc(i, j)] = Sum(i, j);
}
}
}
printf("YES\n");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) printf("%d ", ans[calc(i, j)]);
printf("\n");
}
return 0;
}
看不见我看不见我看不见我
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】博客园2025新款「AI繁忙」系列T恤上架,前往周边小店选购
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· 通过一个DEMO理解MCP(模型上下文协议)的生命周期
· MySQL下200GB大表备份,利用传输表空间解决停服发版表备份问题
· 记一次 .NET某固高运动卡测试 卡慢分析
· 微服务架构学习与思考:微服务拆分的原则
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· Chat to MySQL 最佳实践:MCP Server 服务调用
· .NET周刊【3月第5期 2025-03-30】
· 即时通信SSE和WebSocket对比
· Java程序员的Go入门笔记