每条边不是平行于X轴就是平行于Y轴的矩形,可以用左下角和右上角的点来表示。比如{1, 2, 3, 4},表示的图形如下
给定一个N行4列的二维数组matrix,表示N个每条边不是平行于X轴就是平行于Y轴的矩形。想知道所有的矩形能否组成一个大的完美矩形。完美矩形是指拼出的整体图案是矩形,既不缺任何块儿,也没有重合部分
[要求]
时间复杂度为
,额外空间复杂度为)
第一行一个整数N,表示matrix的行数
接下来N行,每行4个整数分别表示矩形的左下角和右上角的点
若可以拼成一个大的完美矩形,输出"Yes", 否则输出"No"
4 1 1 3 3 3 1 4 2 1 3 2 4 3 2 4 4
No
缺少{2, 3, 3, 4}这一块儿5 1 1 3 3 3 2 4 3 3 2 4 4 1 3 2 4 2 3 3 4
No
拼出的图案缺少{3, 1, 4, 2},并且{3, 2, 4, 2}是重合区域5 1 1 3 3 3 1 4 2 3 2 4 4 1 3 2 4 2 3 3 4
Yes
#include <algorithm>
#include <vector>
#include <string>
#include <unordered_set>
using namespace std;
bool isPerfect(vector<vector<int>>&vec)
{
int index1 = 0, index2 = 0;
int area = 0;
//找出边界
for (int i = 0; i < vec.size(); i++)
{
area += (vec[i][2] - vec[i][0])*(vec[i][3] - vec[i][1]);
if (vec[index1][0] >= vec[i][0] && vec[index1][1] >= vec[i][1])index1 = i;
if (vec[index2][2] <= vec[i][2] && vec[index2][3] <= vec[i][3])index2 = i;
}
//检查边界是否正确,若有超出边界的直接false
for (int i = 0; i < vec.size(); i++)
if (vec[i][0]<vec[index1][0] || vec[i][1]<vec[index1][1] || vec[i][2]>vec[index2][2] || vec[i][3]>vec[index2][3])return false;
//申请额外空间,若恰好为完美矩形,则除了边界外,每个小矩形顶点必重合且只重合两次->充必,不论两局部矩形是T字形还是什么型,只要最终组成一个矩形,大矩形内部的
//所有小矩形的4个顶点必然重合两次,画图则知。
unordered_set<string>set;
for (int i = 0; i < vec.size(); i++)
{
string token = to_string(vec[i][0]) + "-" + to_string(vec[i][1]);
string token3 = to_string(vec[i][0]) + "-" + to_string(vec[i][3]);
string token2 = to_string(vec[i][2]) + "-" + to_string(vec[i][3]);
string token4 = to_string(vec[i][2]) + "-" + to_string(vec[i][1]);
if (set.find(token) != set.end())set.erase(token);
else set.insert(token);
if (set.find(token2) != set.end())set.erase(token2);
else set.insert(token2);
if (set.find(token3) != set.end())set.erase(token3);
else set.insert(token3);
if (set.find(token4) != set.end())set.erase(token4);
else set.insert(token4);
}
for (auto it = set.begin(); it != set.end(); ++it)
{
int splitIndex = it->find("-");
int first = atoi(it->substr(0, splitIndex).c_str());
int second = atoi(it->substr(splitIndex + 1,it->size()-1-splitIndex).c_str());
if (first == vec[index1][0] || first == vec[index2][2] || second == vec[index1][1] || second == vec[index2][3])continue;
return false;
}
return true;
}
int main()
{
int n;
scanf("%d", &n);
vector<vector<int>>vec(n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 4; j++)
{
int tmp;
scanf("%d", &tmp);
vec[i].push_back(tmp);
}
}
printf("%s", isPerfect(vec) ? "Yes" : "No");
} import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.Objects;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Set<Point> counter = new HashSet<>();
int mostDownX = Integer.MAX_VALUE;
int mostDownY = Integer.MAX_VALUE;
int mostUpX = Integer.MIN_VALUE;
int mostUpY = Integer.MIN_VALUE;
int sumOfArea = 0;
for (int i = 0; i < n; i ++) {
String[] strs = br.readLine().split(" ");
int x1 = Integer.parseInt(strs[0]);
int y1 = Integer.parseInt(strs[1]);
int x2 = Integer.parseInt(strs[2]);
int y2 = Integer.parseInt(strs[3]);
mostDownX = Math.min(mostDownX, x1);
mostDownY = Math.min(mostDownY, y1);
mostUpX = Math.max(mostUpX, x2);
mostUpY = Math.max(mostUpY, y2);
sumOfArea += (x2 - x1) * (y2 - y1);
Point leftDown = new Point(x1, y1);
if (!counter.add(leftDown)) {
counter.remove(leftDown);
}
Point leftUp = new Point(x1, y2);
if (!counter.add(leftUp)) {
counter.remove(leftUp);
}
Point rightDown = new Point(x2, y1);
if (!counter.add(rightDown)) {
counter.remove(rightDown);
}
Point rightUp = new Point(x2, y2);
if (!counter.add(rightUp)) {
counter.remove(rightUp);
}
}
// 拼成矩形的四个顶点,需要且只能出现 1 次
if (!counter.contains(new Point(mostDownX, mostDownY))
|| !counter.contains(new Point(mostDownX, mostUpY))
|| !counter.contains(new Point(mostUpX, mostUpY))
|| !counter.contains(new Point(mostUpX, mostDownY))
|| counter.size() != 4) {
System.out.println("No");
return;
}
if (sumOfArea == (mostUpX - mostDownX) * (mostUpY - mostDownY)) {
System.out.println("Yes");
} else {
System.out.println("No");
}
}
}
class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Point that = (Point) obj;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x) ^ Objects.hash(y);
}
}