1 条题解

  • 0
    @ 2025-4-8 13:04:19

    解题思路:

    1. 可以将棋盘上的方格看作图中的节点,若两个方格能被一个多米诺骨牌覆盖,则在这两个节点之间连一条边,这样问题就转化为在一个二分图中寻找完美匹配。
    2. 国际象棋棋盘的方格可以根据行列坐标的奇偶性分为两类,类似二分图的两个部分。移除两个方格后,判断剩余节点能否构成完美匹配,若能则棋盘可被完全覆盖。
    3. 还可以利用棋盘方格的颜色特性,正常的(8×8)棋盘黑白方格数量相等,移除两个方格后,如果黑白方格数量差不是 2 的倍数,那么一定不能被完全覆盖;若数量差是 2 的倍数,再进一步通过搜索算法判断是否存在完美匹配。

    实现步骤

    1. 初始化棋盘状态:根据输入移除指定的两个方格,标记剩余方格的状态。
    2. 判断方格数量和颜色:计算移除两个方格后黑白方格的数量,若数量差不是 2 的倍数,直接返回不能覆盖。
    3. 构建二分图并搜索匹配:将剩余方格按照行列坐标奇偶性分为两个集合,构建二分图。使用深度优先搜索或匈牙利算法在二分图中寻找完美匹配。
    4. 输出结果:根据匹配结果输出相应的信息。 代码:
    #include <iostream>
    #include <vector>
    #include <cstring>
    
    using namespace std;
    
    const int N = 64;
    vector<int> g[N];
    bool st[N];
    int match[N];
    
    // 深度优先搜索寻找增广路
    bool dfs(int u) {
      for (int i = 0; i < g[u].size(); i++) {
          int v = g[u][i];
          if (!st[v]) {
              st[v] = true;
              if (match[v] == -1 || dfs(match[v])) {
                  match[v] = u;
                  return true;
              }
          }
      }
      return false;
    }
    
    // 判断棋盘是否能被覆盖
    bool canCover(int removed1, int removed2) {
      // 初始化图和匹配数组
      for (int i = 0; i < N; i++) {
          g[i].clear();
          match[i] = -1;
      }
    
      // 构建图,根据行列坐标奇偶性连接边
      for (int i = 0; i < 8; i++) {
          for (int j = 0; j < 8; j++) {
              int id = i * 8 + j;
              if (id != removed1 && id != removed2) {
                  if (j + 1 < 8) {
                      int rightId = i * 8 + j + 1;
                      if (rightId != removed1 && rightId != removed2) {
                          g[id].push_back(rightId);
                          g[rightId].push_back(id);
                      }
                  }
                  if (i + 1 < 8) {
                      int downId = (i + 1) * 8 + j;
                      if (downId != removed1 && downId != removed2) {
                          g[id].push_back(downId);
                          g[downId].push_back(id);
                      }
                  }
              }
          }
      }
    
      int matchCount = 0;
      // 使用匈牙利算法寻找最大匹配
      for (int i = 0; i < N; i++) {
          if (i != removed1 && i != removed2) {
              memset(st, 0, sizeof st);
              if (dfs(i)) {
                  matchCount++;
              }
          }
      }
    
      return matchCount == 62;
    }
    
    int main() {
      int k;
      cin >> k;
      for (int i = 1; i <= k; i++) {
          int a, b, c, d;
          cin >> a >> b >> c >> d;
          int removed1 = (a - 1) * 8 + (b - 1);
          int removed2 = (c - 1) * 8 + (d - 1);
    
          cout << "Scenario #" << i << ":" << endl;
          if (canCover(removed1, removed2)) {
              cout << 1 << endl;
          } else {
              cout << 0 << endl;
          }
          cout << endl;
      }
      return 0;
    }
    
    
    • 1

    信息

    ID
    1496
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者