[信息与未来 2023] 电路布线(暂无 SPJ)

题目描述

电路布局布线(Circuit Layout and Routing)是电子设计自动化(EDA)领域的一个重要概念,它涉及到在电路板或集成电路上安排和连接电子元件的过程。这个过程的目标是在满足电气性能、信号完整性、电磁兼容性等要求的同时,实现对空间、成本和生产工艺的优化。

小小现在需要解决一个简化的电路布线问题,在一个 n × m 的方格中进行电路布线。其中:

  • 井号 '#' 标记的格子已经被占用,不能布线。
  • 加号 '+' 标记的格子会连接到电路的其他部分,必须被布线。在给定的电路布线问题中,至少有一个格子必须被布线。
  • 点号 '.' 标记的格子小小有权选择是否布线:布线即将该格标记为加号,不布线即保持为点号。

小小的任务是选择尽可能多的格子进行布线 (将 '.' 的格子标记为 '+'),满足:

  1. 布线电路连通。即从任意一个已布线的格子,都能通过上、下、左、右移动到相邻已布线格子的方式,到达任意另一个布线的格子。
  2. 布线不存在短路 (回路),即不存在某个布线的格子能通过 > 2 步的上、下、左、右移动到相邻布线格子的方式回到自身,且经过的格子各不相同。

例如,以下是一个电路布线问题,已有三个格子被标记为必须布线 (加号):

#....#
....+#
.+####
.+...#

以下展示了一种合法和两种不合法的布线方案:

#+.+.# #.+..# #++..#
+++++# ..+++# .++++#
.+#### .+#### .+####
.++++# .+...# .+...#
合法 不连通 有回路

输入格式

输入第一行是两个空格分隔的整数 nm,代表布线问题格子的行数和列数。

接下来 n 行,每行 m 个字符('#'、'+'、'.' 中的一个),描述了具体的布线问题。

输入数据保证至少存在一种合法的布线方案。输入数据中至少有一个 '+'.

输出格式

输出 n 行,每行 m 个字符,代表最优的布线方案,其中被布线的格子尽可能多。如有多种可能的方案,输出任意一种即可。

样例 #1

样例输入 #1

2 2
+.
..

样例输出 #1

+.
++

样例 #2

样例输入 #2

3 5
...+#
..###
....+

样例输出 #2

++++#
.+###
+++++

样例 #3

样例输入 #3

5 6
..++..
.#..#.
.#..#.
.#..#.
......

样例输出 #3

++++++
+#.+#+ 
+#+.#+
+#++#+
++.+++

提示

数据规模

对于 40% 的数据,满足 n × m ≤ 16

对于 100% 的数据,满足 1≤ n, m ≤ 6

评分标准

在你的布线方案合法(连通且无回路)的前提下:

  • 如果你的方案是最优布线方案,即布线的格子最多,该测试点得满分。
  • 否则,该测试点得一半分数。

本题原始满分为 20pts。

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Point {
    int x, y;
    Point(int a, int b) : x(a), y(b) {}
};

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<char>> grid(n, vector<char>(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> grid[i][j];
        }
    }

    // 找到所有必须布线的点
    vector<Point> mustConnect;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (grid[i][j] == '+') {
                mustConnect.push_back(Point(i, j));
            }
        }
    }

    // BFS,从每个必须布线的点开始,找到所有可以布线的点
    vector<vector<int>> visited(n, vector<int>(m, 0));
    vector<Point> directions = {Point(1, 0), Point(-1, 0), Point(0, 1), Point(0, -1)};
    for (auto point : mustConnect) {
        queue<Point> q;
        q.push(point);
        visited[point.x][point.y] = 1;
        while (!q.empty()) {
            Point p = q.front();
            q.pop();
            for (auto dir : directions) {
                int x = p.x + dir.x;
                int y = p.y + dir.y;
                if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == '.' && visited[x][y] == 0) {
                    visited[x][y] = 1;
                    q.push(Point(x, y));
                }
            }
        }
    }

    // 根据visited数组,布线
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (visited[i][j] == 1) {
                grid[i][j] = '+';
            }
        }
    }

    // 输出结果
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << grid[i][j];
        }
        cout << endl;
    }

    return 0;
}

原文地址: https://www.cveoy.top/t/topic/o60s 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录