1011 Cut Rectangles (35分)(C++)

 

When a rectangle is cut by a straight line, we can easily obtain two polygons as the result. But the reversed problem is harder: given two polygons, your task is to check whether or not they could be obtained by cutting a rectangle.

To give you more trouble, the input polygons are possibly moved, rotated (90 degrees, 180 degrees, or 270 degrees counter-clockwise), or even flipped (mirrored).

It is assumed that the original rectangle's edges are parallel to the axis.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤20), and then N pairs of polygons are given. Each polygon is described in the format:

k x​1​​ y​1​​ ⋯ x​k​​ y​k​​

where k (2<k≤10) is the number of vertices on the polygon, and (x​i​​, y​i​​) (0≤x​i​​,y​i​​≤10​8​​) are the coordinates of the vertices, given in either clockwise or counter-clockwise order.

Note: there is no redundant vertex. That is, it is guaranteed that all the vertices are distinct for each polygon, and that no three consecutive vertices are on the same line.

Output Specification:

For each pair of polygons, print in a line either YES or NO as the answer.

Sample Input:

8
3 0 0 1 0 1 1
3 0 0 1 1 0 1
3 0 0 1 0 1 1
3 0 0 1 1 0 2
4 0 4 1 4 1 0 0 0
4 4 0 4 1 0 1 0 0
3 0 0 1 1 0 1
4 2 3 1 4 1 7 2 7
5 10 10 10 12 12 12 14 11 14 10
3 28 35 29 35 29 37
3 7 9 8 11 8 9
5 87 26 92 26 92 23 90 22 87 22
5 0 0 2 0 1 1 1 2 0 2
4 0 0 1 1 2 1 2 0
4 0 0 0 1 1 1 2 0
4 0 0 0 1 1 1 2 0

Sample Output:

YES
NO
YES
YES
YES
YES
NO
YES

題目大意:有一個矩形,可以由一條直線分割成兩個多邊形,先給出兩個多邊形的各個頂點,判斷這兩個多邊形能不能拼成一個矩形。爲了簡化題目,原矩形與座標軸平行。給出的多邊形可能在座標系中進行了平移、旋轉(90度的倍數),翻轉。多邊形給出點的時候按順時針/逆時針進行。

解題思路:暴力求解o(* ̄︶ ̄*)o

三角形+三角形:兩個三角形全等,且兩個三角形爲直角三角形

四邊形+四邊形:(1)矩形+矩形:有一條邊相等

                           (2)直角梯形+直角梯形:兩腰相等,且兩個梯形的上下底可組合相加相等(a上底+b下底 = a下底+b下底)

三角形+四邊形:三角形爲直角三角形,四邊形爲直角梯形,三角形斜邊=梯形非直角邊的腰,三角形直角邊a+梯形上底=梯形下底,三角形直角邊b=梯形直角邊腰

三角形+五邊形:三角形爲直角三角形,五邊形有3個直角,三角形斜邊=五邊形非直角邊a,三角形直角邊a‘+五邊形a的旁邊邊b=五邊形b的對邊,三角形直角邊b‘五邊形a的另一旁邊邊c=五邊形c的對邊

calEdge:計算每條邊的長度

calAngel:判斷該頂點是不是直角(因爲原矩形平行,且旋轉角度均爲90的倍數,所以這裏的判斷可以用是否與座標軸平行來判斷)

getHypotenuse:且兩端頂點均不爲直角的邊的序號(斜邊序號)

#include <bits/stdc++.h>
using namespace std;
int n, ka, kb, ha, hb;
bool flag;
vector<int> ea, eb;
vector<bool> aa, ab;
vector<int> calEdge(vector<pair<int, int>> v){
	vector<int> e;
	for(int i = 0; i < v.size(); ++ i){
		int Right = i == v.size()-1 ? 0 : i+1;
		e.push_back(sqrt((v[i].first - v[Right].first)*(v[i].first - v[Right].first) + (v[i].second - v[Right].second)*(v[i].second - v[Right].second)));
	}
	return e;
}
vector<bool> calAngel(vector<pair<int, int>> v){
	vector<bool>angel;
	for(int i = 0; i < v.size(); ++ i){
		int Left = i == 0 ? v.size()-1 : i - 1, Right = i == v.size()-1 ? 0 : i+1;
		angel.push_back((v[Left].first == v[i].first && v[i].second == v[Right].second) || (v[Left].second == v[i].second && v[i].first == v[Right].first));
	}
	return angel;
}
int getHypotenuse(vector<bool> angel){
	int ans = -2, cnt = 0;
	for(int i = 0; i < angel.size(); ++ i){
		int Left = i == 0 ? angel.size()-1 : i-1;
		if(angel[i]) ++ cnt;
		else if(angel[Left])
			ans = i;
	}
	return cnt >= (angel.size()-2) ? ans : -1;
}
int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; ++ i){
		flag = false;
		scanf("%d", &ka);
		vector<pair<int, int>> pointa(ka);
		for(int j = 0; j < ka; ++ j)
			scanf("%d %d", &pointa[j].first, &pointa[j].second);
		scanf("%d", &kb);
		vector<pair<int, int>> pointb(kb);
		for(int j = 0; j < kb; ++ j)
			scanf("%d %d", &pointb[j].first, &pointb[j].second);
		if(ka > kb)
			swap(pointa, pointb);
		ea = calEdge(pointa), eb = calEdge(pointb);
		aa = calAngel(pointa), ab = calAngel(pointb);
		ha = getHypotenuse(aa), hb = getHypotenuse(ab);
		if(ha == -1 || hb == -1);
		else if(ka == 3 && kb == 3){	
			sort(ea.begin(), ea.end()), sort(eb.begin(), eb.end());
			if(ea == eb)
				flag = true;
		}
		else if(ka == 4 && kb == 4){
			if(ha == -2 || hb == -2){
				if(ha == -2 && hb == -2 && (ea[0]==eb[0] || ea[0] == eb[1] || ea[1] == eb[1] || ea[1] == eb[0]))
					flag = true;
			}
			else if(ea[ha]==eb[hb] && ea[(ha+2)%4]==eb[(hb+2)%4] && (((ea[(ha+1)%4]+eb[(hb+1)%4])==(ea[(ha+3)%4]+eb[(hb+3)%4])) || ((ea[(ha+1)%4]+eb[(hb+3)%4])==(ea[(ha+3)%4]+eb[(hb+1)%4]))))
				flag = true;
		}
		else if((ka == 3 && kb == 4) || (ka == 4 && kb == 3)){
			if(ea[ha]==eb[hb] && (ea[(ha+2)%3]==eb[(hb+2)%4]&&(ea[(ha+1)%3]+min(eb[(hb+1)%4],eb[(hb+3)%4])==max(eb[(hb+1)%4],eb[(hb+3)%4]))) || (ea[(ha+1)%3]==eb[(hb+2)%4]&&(ea[(ha+2)%3]+min(eb[(hb+1)%4],eb[(hb+3)%4])==max(eb[(hb+1)%4],eb[(hb+3)%4]))))
				flag = true;
		}
		else if((ka == 3 && kb == 5) || (ka == 5 && kb == 3)){
			if(ea[ha]==eb[hb] && (((ea[(ha+2)%3]+min(eb[(hb+2)%5],eb[(hb+4)%5])==max(eb[(hb+2)%5],eb[(hb+4)%5]))&&(ea[(ha+1)%3]+min(eb[(hb+1)%5],eb[(hb+3)%5])==max(eb[(hb+1)%5],eb[(hb+3)%5]))) || ((ea[(ha+1)%3]+min(eb[(hb+2)%5],eb[(hb+4)%5])==max(eb[(hb+2)%5],eb[(hb+4)%5]))&&(ea[(ha+2)%3]+min(eb[(hb+1)%5],eb[(hb+3)%5])==max(eb[(hb+1)%5],eb[(hb+3)%5])))))
				flag = true;
		}
		printf("%s\n", flag ? "YES" : "NO");
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章