📜  门| Gate IT 2008 |问题13(1)

📅  最后修改于: 2023-12-03 14:58:23.883000             🧑  作者: Mango

门 | Gate IT 2008 | 问题13

题目描述

问题13是2008年Gate IT考试的一道编程问题。问题描述如下:

给定 $n$ 个大小相同的正方形,它们在平面上的位置是确定的。它们根据它们的重叠部分被分组。例如,下面是5个正方形被分成3组的一种可能。

1   2
 3 4
   5

在给定的条件下,你的任务是计算 5 个正方形是否存在一个 '门'(门是指由两组正方形A和B组成的一个开放结构,其中A的所有正方形与B的所有正方形彼此都没有公共部分),并给出门的数量。

输入格式

输入的第一行包含一个整数 $n$,表示正方形的数量。

接下来 $n$ 行,每行包含4个整数 $x_i, y_i, w_i, h_i$,表示第 $i$ 个正方形的位置和大小。

输出格式

输出门的数量。

示例输入1
5
20 20 10 10
40 20 10 10
30 40 10 10
60 40 10 10
50 60 10 10
示例输出1
1
问题分析

这道题我们可以用暴力的方式枚举所有可能的门的组合。我们可以枚举正方形的位置来确定组合,然后检查门是否存在(即两个组没有公共部分)。

具体算法的流程如下:

  1. 用一个数组存储每个正方形所属的组。
  2. 依次枚举每个正方形,将它所属的组与其他正方形的组进行比较,如果没有相交的部分,则将两个组合并。
  3. 最后,如果一个组可以与其他组合并,则这些组都是门。
代码实现
````cpp
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 110;
int n;
struct Node {
    int x, y, w, h;
} q[N];

int p[N];
int Find(int x) {
    if (p[x] != x) p[x] = Find(p[x]);
    return p[x];
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) p[i] = i;
    for (int i = 1; i <= n; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        q[i] = {a, b, c, d};
        for (int j = 1; j < i; j++) {
            int x1 = q[i].x, y1 = q[i].y, x2 = x1 + q[i].w, y2 = y1 + q[i].h;
            int x3 = q[j].x, y3 = q[j].y, x4 = x3 + q[j].w, y4 = y3 + q[j].h;
            if ((x1 <= x4 && x3 <= x2) && (y1 <= y4 && y3 <= y2)) p[Find(i)] = Find(j);
        }
    }
    vector<int> v;
    for (int i = 1; i <= n; i++) if (Find(i) == i) v.push_back(i);
    int ans = 0;
    for (int i = 0; i < v.size(); i++)
        for (int j = i + 1; j < v.size(); j++) {
            int cnt = 0;
            for (int k = 1; k <= n; k++) {
                int fx = Find(k), fy = Find(v[i]), fz = Find(v[j]);
                if (fx == fy || fx == fz) cnt++;
            }
            if (cnt == n) ans++;
        }
    cout << ans << endl;
    return 0;
}