PAT | T1011 Cut Rectangles

写了一个半小时,测试点3和4答案错误,应该是某个情况没考虑到(我觉得应该是翻转没考虑)扣了三分,还行吧,考试的时候这三分就不要了
以下是AC代码(附详细注释):

#include <iostream>
#include <vector>
#include <climits>
#include <cmath>

using namespace std;

struct Edge{
	double k; // 斜率
	int x1,y1,x2,y2; // 两个点坐标
	double len; // 长度
};

struct Rectangle{
	int k; // k边形
	vector<int> x; // 各点x坐标
	vector<int> y; // 各点y坐标
	vector<Edge> edges; // 边
};

Rectangle process(Rectangle r){ // 预处理每个多边形
	int x = r.x[0],y = r.y[0];
	for(int i = 1;i < r.k;i++){
		int x1 = r.x[i],y1 = r.y[i];
		Edge e;
		if(x1 != x) e.k = (double)(y1 - y) / (x1 - x);
		else e.k = INT_MAX;
		e.x1 = x,e.x2 = x1,e.y1 = y,e.y2 = y1;
		e.len = sqrt((double)(x - x1) * (x - x1) + (double)(y - y1) * (y - y1));
		x = x1,y = y1;
		r.edges.push_back(e);
	}
	int x1 = r.x[0],y1 = r.y[0];
	Edge e;
	if(x1 != x) e.k = (double)(y1 - y) / (x1 - x);
	else e.k = INT_MAX;
	e.x1 = x,e.x2 = x1,e.y1 = y,e.y2 = y1;
	e.len = sqrt((double)(x - x1) * (x - x1) + (double)(y - y1) * (y - y1));
	r.edges.push_back(e);
	return r;
}

bool vertical(Edge e1,Edge e2){
	return (e1.k * e2.k == -1) || (e1.k == 0 && e2.k == INT_MAX) || (e1.k == INT_MAX && e2.k == 0);
}

bool operator!=(Edge e1,Edge e2){
	return (e1.len != e2.len); // 两条边长度不等 || 两条边不垂直 || 两条边不平行
}

bool operator==(Edge e1,Edge e2){
	return e1.len == e2.len; // 两条边长度相等 && (两条边垂直 || 两条边平行)
}

void func1(Rectangle r1, Rectangle r2){ // 两个四边形的情况
	r1 = process(r1),r2 = process(r2);
	// 每个四边形均有至少两个相邻的直角,且至少有两条不相邻的边相同长度
	// 剩下两条边之和相等
	Edge e11,e12,e21,e22; // 直角夹的两条边和该边的对边
	Edge e13,e14,e23,e24; // 剩下的两条边
	bool r1Find = false,r2Find = false;
	for(int i = 0;!(r1Find && r2Find) && i < 4;i++){ // 判断直角
		if(vertical(r1.edges[i],r1.edges[(i + 1) % 4])){ // 找到一个直角
			// 那么看它的下一个或前一个是不是直角
			// 下一个
			if(!r1Find && vertical(r1.edges[(i + 1) % 4],r1.edges[(i + 2) % 4])){ // 下一个是直角
				e11 = r1.edges[i],e12 = r1.edges[(i + 2) % 4];
				e13 = r1.edges[(i + 1) % 4],e14 = r1.edges[(i + 3) % 4];
				r1Find = true;
			}
			// 前一个
			if(!r1Find && vertical(r1.edges[(i + 3) % 4],r1.edges[i])){ // 前一个是直角
				e11 = r1.edges[(i + 3) % 4],e12 = r1.edges[(i + 1) % 4];
				e13 = r1.edges[(i + 2) % 4],e14 = r1.edges[i];
				r1Find = true;
			}
		}
		if(vertical(r2.edges[i],r2.edges[(i + 1) % 4])){ // 找到一个直角
			// 那么看它的下一个或前一个是不是直角
			// 下一个
			if(!r2Find && vertical(r2.edges[(i + 1) % 4],r2.edges[(i + 2) % 4])){ // 下一个是直角
				e21 = r2.edges[i],e22 = r2.edges[(i + 2) % 4];
				e23 = r2.edges[(i + 1) % 4],e24 = r2.edges[(i + 3) % 4];
				r2Find = true;
			}
			// 前一个
			if(!r2Find && vertical(r2.edges[(i + 3) % 4],r2.edges[i])){ // 前一个是直角
				e21 = r2.edges[(i + 3) % 4],e22 = r2.edges[(i + 1) % 4];
				e23 = r2.edges[(i + 2) % 4],e24 = r2.edges[i];
				r2Find = true;
			}
		}
	}
	if(r1Find == false || r2Find == false){ // 没有找到这样的直角
		printf("NO\n");
		return;
	}
	if(e11 != e21 || e12 != e22){
		printf("NO\n");
		return;
	}
	if(e13.len + e23.len == e14.len + e24.len || e13.len + e24.len == e14.len + e23.len){
		printf("YES\n");
		return;
	}else{
		printf("NO\n");
		return;
	}
}

void func2(Rectangle r1,Rectangle r2){ // 两个三角形的情况
	r1 = process(r1),r2 = process(r2);
	// 有且仅有一个直角,且直角对边必须相等,且直角的两个邻边也必须相等
	Edge e11,e21; // 直角对边
	Edge e12,e13,e22,e23; // 直角邻边
	bool r1Find = false,r2Find = false;
	for(int i = 0;!(r1Find && r2Find) && i < 3;i++){
		if(vertical(r1.edges[i],r1.edges[(i + 1) % 3])){ // 找到一个直角
			r1Find = true;
			e11 = r1.edges[(i + 2) % 3];
			e12 = r1.edges[i],e13 = r1.edges[(i + 1) % 3];
		}
		if(vertical(r2.edges[i],r2.edges[(i + 1) % 3])){ // 找到一个直角
			r2Find = true;
			e21 = r2.edges[(i + 2) % 3];
			e22 = r2.edges[i],e23 = r2.edges[(i + 1) % 3];
		}
	}
	if(r1Find == false || r2Find == false){ // 没有找到这样的直角
		printf("NO\n");
		return;
	}
	if(e11 != e21){
		printf("NO\n");
		return;
	}
	if((e12 == e22 && e13 == e23) || (e12 == e23 && e13 == e22)){
		printf("YES\n");
		return;
	}else{
		printf("NO\n");
		return;
	}
}

void func3(Rectangle r1,Rectangle r2){ // 一个三角形一个五边形的情况,默认r1是三角形
	// 三角形里必须有一个直角
	// 五边形里必须有三个连着的直角,且中间那个直角的对边必须和三角形里直角的对边相等
	r1 = process(r1),r2 = process(r2);
	Edge e11,e21; // 两个直角的对边
	bool r1Find = false,r2Find = false;
	for(int i = 0;!r1Find && i < 3;i++){ // 在三角形里找直角
		if(vertical(r1.edges[i],r1.edges[(i + 1) % 3])){ // 找到一个直角
			r1Find = true;
			e11 = r1.edges[(i + 2) % 3];
		}
	}
	for(int i = 0;!r2Find && i < 5;i++){ // 在五边形里找直角
		if(vertical(r2.edges[i],r2.edges[(i + 1) % 5])){ // 找到一个直角
			// 看前一个和后一个是否是直角
			if(vertical(r2.edges[(i + 1) % 5],r2.edges[(i + 2) % 5]) && vertical(r2.edges[i],r2.edges[(i + 4) % 5])){ // 找到了
				r2Find = true;
				e21 = r2.edges[(i + 3) % 5];
			}
		}
	}
	if(r1Find == false || r2Find == false){ // 没有找到这样的直角
		printf("NO\n");
		return;
	}
	if(e11 == e21){
		printf("YES\n");
		return;
	}
	else{
		printf("NO\n");
		return;
	}
}

void func4(Rectangle r1,Rectangle r2){ // 一个三角形一个四边形的情况,默认r1是三角形
	// 三角形必须有一个直角
	// 四边形必须有两个直角
	// 四边形直角边缘的边加上三角形某一条直角边必须等于四边形直角另一个边缘的边
	// 且四边形两个直角中间的边必须等于三角形另一条直角边
	r1 = process(r1),r2 = process(r2);
	bool r1Find = false,r2Find = false;
	Edge e11,e21,e22; // 三角形直角对边和四边形直角边缘的两条边
	Edge e12,e13,e23; // 三角形两条直角边和四边形两直角中间的边
	for(int i = 0;!r1Find && i < 3;i++){ // 在三角形里找直角
		if(vertical(r1.edges[i],r1.edges[(i + 1) % 3])){ // 找到一个直角
			r1Find = true;
			e11 = r1.edges[(i + 2) % 3];
			e12 = r1.edges[(i + 1) % 3],e13 = r1.edges[i];
		}
	}
	for(int i = 0;!r2Find && i < 4;i++){ // 在四边形里找直角
		if(vertical(r2.edges[i],r2.edges[(i + 1) % 4])){ // 找到一个直角
			// 那么看它的下一个或前一个是不是直角
			// 下一个
			if(!r2Find && vertical(r2.edges[(i + 1) % 4],r2.edges[(i + 2) % 4])){ // 下一个是直角
				e21 = r2.edges[i],e22 = r2.edges[(i + 2) % 4];
				e23 = r2.edges[(i + 1) % 4];
				r2Find = true;
			}
			// 前一个
			if(!r2Find && vertical(r2.edges[(i + 3) % 4],r2.edges[i])){ // 前一个是直角
				e21 = r2.edges[(i + 3) % 4],e22 = r2.edges[(i + 1) % 4];
				e23 = r2.edges[i];
				r2Find = true;
			}
		}
	}
	if(r1Find == false || r2Find == false){ // 没有找到这样的直角
		printf("NO\n");
		return;
	}
	if((e12 == e23 && (e13.len + e21.len == e22.len || e13.len + e22.len == e21.len)) || 
		(e13 == e23 && (e12.len + e21.len == e22.len || e12.len + e22.len == e21.len))){
		printf("YES\n");
		return;
	}else{
		printf("NO\n");
		return;
	}
}

int main(){
	int n;
	scanf("%d",&n);
	for(int i = 0;i <n;i++){
		Rectangle r1,r2;
		scanf("%d",&r1.k);
		for(int j = 0;j < r1.k;j++){
			int tmpx,tmpy;
			scanf("%d%d",&tmpx,&tmpy);
			r1.x.push_back(tmpx);
			r1.y.push_back(tmpy);
		}
		scanf("%d",&r2.k);
		for(int j = 0;j < r2.k;j++){
			int tmpx,tmpy;
			scanf("%d%d",&tmpx,&tmpy);
			r2.x.push_back(tmpx);
			r2.y.push_back(tmpy);
		}
		if(r1.k == r2.k && r1.k == 4){ // 两个四边形
			func1(r1,r2);
		}else if(r1.k == r2.k && r1.k == 3){ // 两个三角形
			func2(r1,r2);
		}else if(r1.k + r2.k == 8 && (r1.k == 3 || r2.k == 3)){ // 一个三角形,一个五边形
			if(r1.k == 3) func3(r1,r2);
			else func3(r2,r1);
		}else if(r1.k + r2.k == 7 && (r1.k == 3 || r2.k == 3)){ // 一个三角形,一个四边形
			if(r1.k == 3) func4(r1,r2);
			else func4(r2,r1);
		}else{
			printf("NO\n");
		}
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值