Codefoces 13B Letter A (几何)

题意:给你任意的三条线段的坐标,问能否组成合格的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;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值