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");
	}
}

 

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