CF1567F One-Four Overload

CF1567F One-Four Overload

我居然把这道 2700 的题切了!!!

OHHHHHHHHHHHHHHHH!!!

没有标记的格子只能选 1 或者 4 , 标记的格子必须是 5 的倍数.

比较显然的是, 标记的格子周围必须有且只能有偶数个 (包括 0 ) 未标记的格子, 否则无解.

接下来我们考虑构造一组解.

比较显然的是, 如果一个标记的格子周围只有两个未标记的格子, 那么一定是一个 1 一个 4 , 不管是 L 形还是 I 形.

如果有 4 个呢? 那么我们就把同一行的和同一列的填上相同的数. 为什么?

因为一对 I 形的未标记格子只可能对应一个标记的格子, 而一对 L 形的可能对应两个标记的格子, 所以我们只需要保证这 4 个未标记格子分别组成的两组 L 形合法就够了.

所以我们就判断一下, 如果这个标记的格子周围只有两个未标记的, 直接连边, 四个的话, 把四个 L 连起来, 注意, 是双向边.

code:

#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;
}
posted @   sshadows  阅读(46)  评论(0)    收藏  举报
编辑推荐:
· 解锁.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入门笔记
点击右上角即可分享
微信分享提示