每条边不是平行于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); } }