PAT顶级 1011 Cut Rectangles (35分)(思维题)

题目链接:

PAT顶级 1011 Cut Rectangles (35分)

思路:

1.首先我们需要分析出,如果两个图形是被一个矩形切一次所形成,那么这两个图形只可能是(1)三角形+四边形(2)三角形+三角形(3)三角形+五边形(4)四边形+四边形;
2.其次我们再思考一下,这条切线如果与坐标轴平行,那么会得到两个矩形,且这两个矩形至少有一条边互相相等,这种情况我们需要讨论一下(归类在四边形+四边形中);如果与坐标轴不平行呢?那么这种情况,这两个图形只有被切割形成的那一条边是不平行于坐标轴的,其它边都平行于坐标轴,因此我们只需要将题目给我们的两个图形中不平行于坐标轴的边拿出来分析即可;
3.因为题目给的图形的点是按顺序给出的,我们只需要比较两两相邻的点,如果两个点的横坐标和纵坐标都不相等,那么这条边必定不和坐标轴平行;
4.此时如果能输出YES的情况必定是:两个图形都有且仅有一条不平行于坐标轴的边,(一条不平行于坐标轴的边必定可以和两条平行于坐标轴的直线形成一个直角三角形),这两个边所形成的直角三角形全等;
5.这样做会WA最后一个测试点,因为有一个情况漏考虑了:
在这里插入图片描述
在含有三角形的情况下不会产生特殊情况,但是在四边形+四边形中,则会产生两个图形唯一的斜边等价、却不能拼成矩形的情况,此时我们需要特殊判定一下这两个直角梯形的直角腰是否相等即可;

代码:

#include<bits/stdc++.h>
#define pb(x) push_back(x)
using namespace std;
int flag;
vector<int> v[2],n,len;
void deal(vector<int>& a,vector<int>& b,int id){
	int sz=a.size(); set<int> st;
	for(int i=0;i<sz;i++)
		if(a[i]!=a[(i+1)%sz]&&b[i]!=b[(i+1)%sz]){
			st.insert((i+1)%sz); st.insert(i);
			if(sz==4) len.pb(abs(a[(i+2)%4]-a[(i+3)%4])+abs(b[(i+2)%4]-b[(i+3)%4]));  //存储直角腰的长度 
		}
	if(st.size()==0){   //是矩形 
		v[id].pb(abs(a[2]-a[0])); v[id].pb(abs(b[2]-b[0])); flag++;
	}else for(int i:st) v[id].pb(a[i]),v[id].pb(b[i]);   //存储斜边 
}
void solve(){
	if(n[0]<6&&n[1]<6&&n[0]+n[1]<9){
		if(flag==2){
			int a=v[0][0],b=v[0][1],c=v[1][0],d=v[1][1];
			if(a==c||a==d||b==c||b==d){puts("YES");return;}
		}else if(flag==0){
			if(v[0].size()==4&&v[1].size()==4){
				if(n[0]==4&&n[1]==4&&len[0]!=len[1]){puts("NO");return;}  //特判直角腰 
				int a=abs(v[0][2]-v[0][0]),b=abs(v[0][3]-v[0][1]); if(a>b) swap(a,b);
				int c=abs(v[1][2]-v[1][0]),d=abs(v[1][3]-v[1][1]); if(c>d) swap(c,d);
				if(a==c&&b==d) {puts("YES");return;}
			}
		}
	}
	puts("NO");
}
int main(){
//	freopen("Sakura.txt","r",stdin);
	int kase; cin>>kase;
	while(kase--){
		flag=0; n.clear(); len.clear();
		for(int i=0;i<2;i++){
			v[i].clear();
			int k; cin>>k; n.pb(k); vector<int> a(k),b(k);
			for(int i=0;i<k;i++) cin>>a[i]>>b[i];
			deal(a,b,i);
		}
		solve();
	}
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308738.html