题意:给你任意的三条线段的坐标,问能否组成合格的A。这里有三条限制:1.任意其中两条必有一个公共点,注意,一定是一个,并且没有公共点的第三条边的两个端点要在那两条有公共边的边上;2.两条有公共点的边的夹角大于0度小于等于90度;3.这两条边被第三条边所划分的,分别各自被划分为两条,其中较长的不能大于较短的4倍。
思路:一步一步来,就是每提交一次就WA,然后每想到特殊情况加上特判,很是悲剧啊......
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
inline __int64 min(__int64 a,__int64 b)
{
return a<b?a:b;
}
inline __int64 max(__int64 a,__int64 b)
{
return a>b?a:b;
}
inline __int64 abs(__int64 a)
{
return a<0?(-a):a;
}
struct node{
__int64 x[2],y[2];
}data[3];
inline __int64 dis(__int64 x,__int64 y,__int64 x1,__int64 y1)
{
return (x-x1)*(x-x1)+(y-y1)*(y-y1);
}
int main()
{
int ca;
cin>>ca;
while(ca--)
{
bool sign=false;
for(int i=0;i<3;i++)
cin>>data[i].x[0]>>data[i].y[0]>>data[i].x[1]>>data[i].y[1];
for(int i=0;i<3;i++)
if(data[i].x[0]==data[i].x[1]&&data[i].y[0]==data[i].y[1])//如果出现不是线段,也就是两个endpoint一样了,输出NO
{
sign=true;
break;
}
if(sign) {cout<<"NO"<<endl;continue;}
sign=false;
int flagi=0,flagj=0;
int signi=0,signj=0;
__int64 xt,yt;
for(int i=0;i<3;i++)
for(int k=i+1;k<3;k++)
for(int j=0;j<2;j++)
for(int l=0;l<2;l++)
{
if(data[i].x[j]==data[k].x[l]&&data[i].y[j]==data[k].y[l])
{
if(!sign)
{
flagi=i,flagj=k;
signi=j,signj=l;
xt=data[i].x[j],yt=data[i].y[j];
sign=true;
}
else //如果出现两个点以上的重复坐标,输出NO
{
sign=false;
}
}
}
if(!sign) {cout<<"NO"<<endl;continue;}
sign=false;
__int64 a=xt,b=yt,c=data[flagi].x[signi^1],d=data[flagi].y[signi^1],e=data[flagj].x[signj^1],f=data[flagj].y[signj^1];//(a,b)为顶点,(c,d),(e,f)为
int flagk; //另两个顶点
__int64 g,h,m,n;//查找第三条边,并将在(a,b)-(c,d)边上的点赋值为(g,h),在(a,b)-(e,f)边上的点赋值为(m,n)
for(int i=0;i<3;i++)
if(i!=flagi&&i!=flagj)
{flagk=i;break;}
for(int i=0;i<2;i++)
{
if(((data[flagk].x[i]-a)*(d-b)==(data[flagk].y[i]-b)*(c-a))&&((data[flagk].x[i^1]-a)*(f-b)==(data[flagk].y[i^1]-b)*(e-a)))
{
g=data[flagk].x[i],h=data[flagk].y[i],m=data[flagk].x[i^1],n=data[flagk].y[i^1];
sign=true;
break;
}
}
if(((g<min(a,c)||g>max(a,c))||(h<min(b,d)||h>max(b,d)))||((m<min(a,e)||m>max(a,e))||(n<min(b,f)||n>max(b,f)))) {cout<<"NO"<<endl;continue;}
//若第三条边的两个端点有一个不在前两条边上,输出NO
if(g==m&&h==n) sign=false;
if((abs((g-m)*(d-b))==abs((h-n)*(c-a)))||(abs((g-m)*(f-b))==abs((h-n)*(e-a)))) sign=false;//如果第三条边的两个点都在前两条边的某条边上,输出NO
if(!sign) {cout<<"NO"<<endl;continue;}
sign=false;
if(dis(a,b,c,d)+dis(a,b,e,f)>=dis(c,d,e,f)) //判断夹角
{
__int64 minedge[2],maxedge[2]; //一下判断较长边是否小于等于4倍的较短边
if(dis(g,h,a,b)>dis(g,h,c,d))
{
minedge[0]=dis(g,h,c,d);
maxedge[0]=dis(g,h,a,b);
}
else
{
minedge[0]=dis(g,h,a,b);
maxedge[0]=dis(g,h,c,d);
}
if(dis(m,n,a,b)>dis(m,n,e,f))
{
minedge[1]=dis(m,n,e,f);
maxedge[1]=dis(m,n,a,b);
}
else
{
minedge[1]=dis(m,n,a,b);
maxedge[1]=dis(m,n,e,f);
}
if(minedge[0]*16>=maxedge[0]&&minedge[1]*16>=maxedge[1])
sign=true;
}
if(sign) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}