UVA11800 Determine the Shape


题意得:

1.Square         四条边相等,四个角相等

2.Rectangle          对边相等,四个角相等

3.Rhombus        四条边相等,对角相等

4.Parallelogram       对边相等,对边平行

5.Trapezium       两条边平行

6.Ordinary Quadrilateral  前面条件不满足,就输出这个

思路:由于题目给出的样例告诉我们点不是按照顺序给的,于是先对点按逆时针排序ABCD

逆时针排序的方法是凸包,ch[ ]为凸包的点

但其实有一种方法可以不用凸包的,从一般四边形开始到正方形,用一个值记录最大符合哪一种形状,

用一个函数去实现,调用(a,b,c,d),(a,c,b,d),(a,b,d,c)来处理顺序不同的情况,由于我不是这种做法,我这里不展开,可以见这位大佬的博客

A=ch[0],B=ch[1],C=ch[2],D=ch[3];

再分别求出各个点的距离

        double sab,sbc,scd,sda,sad,sac,sbd;
        sab=get_length(B-A),sbc=get_length(C-B);
        scd=get_length(D-C),sda=get_length(A-D);

各个点的角度

        //求角度 
        double a,b,c,d;
        a=get_angle(D-A,B-A);
        b=get_angle(A-B,C-B);
        c=get_angle(B-C,D-C);
        d=get_angle(C-D,A-D);    

需要加入一个特判,虽然题目里面说不会存在三点共线的问题,但还是存在的,使凸包会退化成线或者点

        if(n<4)
        {
            printf("Ordinary Quadrilateral\n");
            continue;
        }

判断形状

cross是叉积判断是否平行,平行的情况为0

        if(dcmp(a-b)==0 && dcmp(b-c)==0 && dcmp(c-d)==0 && dcmp(d-a)==0 && dcmp(sab-sbc)==0 && dcmp(sbc-scd)==0 && dcmp(scd-sda)==0)
        {
            printf("Square\n");
        }
        else if(dcmp(a-b)==0 && dcmp(b-c)==0 && dcmp(c-d)==0 && dcmp(d-a)==0 && dcmp(sab-scd)==0 && dcmp(sda-sbc)==0)
        {
            printf("Rectangle\n");
        }
        else if(dcmp(sab-sbc)==0 && dcmp(sbc-scd)==0 && dcmp(scd-sda)==0&&dcmp(a-c)==0&&dcmp(b-d)==0)
        {
            printf("Rhombus\n");
        }
          else if(dcmp(sab-scd)==0 && dcmp(sbc-sda)==0&&dcmp(a-c)==0&&dcmp(b-d)==0)
          {
              printf("Parallelogram\n");
          }
          else if(dcmp(cross(B-A,C-D))==0 || dcmp(cross(C-B,D-A))==0)
          {
              printf("Trapezium\n");
          }
          else 
          {
              printf("Ordinary Quadrilateral\n");
          }
          

完整AC代码:

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 using namespace std;
  7 
  8 #define x first
  9 #define y second 
 10 
 11 const double eps=1e-9;
 12 typedef pair<double,double>PDD;
 13 
 14 PDD A,B,C,D;
 15 
 16 PDD operator - (PDD A,PDD B)
 17 {
 18     return PDD{A.x-B.x,A.y-B.y};
 19 }
 20 int dcmp(double x)
 21 {
 22     if(fabs(x)return 0;
 23     if(x<0)        return -1;
 24     return 1;
 25 }
 26 
 27 
 28 double get_length(PDD A)
 29 {
 30     return sqrt(A.x*A.x+A.y*A.y);
 31 }
 32 
 33 
 34 double dot(PDD A,PDD B)
 35 {
 36     return A.x*B.x+A.y*B.y;
 37 }
 38 
 39 double get_angle(PDD A,PDD B)
 40 {
 41     return acos(dot(A,B)/get_length(A)/get_length(B));
 42 }
 43 
 44 double cross(PDD A,PDD B)
 45 {
 46     return A.x*B.y-A.y*B.x;
 47 }
 48 
 49 
 50 int convexhull(PDD* p,int n,PDD* ch)
 51 {
 52     p[0]=A,p[1]=B,p[2]=C,p[3]=D;
 53     sort(p,p+n);
 54     int m=0;
 55     for(int i=0;i)
 56     {
 57         while(m>1 && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)    m--;
 58         ch[m++]=p[i]; 
 59     }
 60     int k=m;
 61     for(int i=n-2;i>=0;i--)
 62     {
 63         while(m>k && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)    m--;
 64         ch[m++]=p[i];
 65     }
 66     if(n>1) m--;
 67     
 68     A=ch[0],B=ch[1],C=ch[2],D=ch[3];
 69     //逆时针赋值
 70     return m;
 71 }
 72 
 73 
 74 int main()
 75 {
 76     int t,flag=0;
 77     cin>>t;
 78     while(t--)
 79     {
 80         PDD ch[10],p[10];
 81         double x1,y1,x2,y2,x3,y3,x4,y4;
 82         cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
 83         
 84         A={x1,y1},B={x2,y2},C={x3,y3},D={x4,y4};
 85         p[0]=A,p[1]=B,p[2]=C,p[3]=D;
 86         
 87         int n=convexhull(p,4,ch);
 88         
 89         double sab,sbc,scd,sda,sad,sac,sbd;
 90         sab=get_length(B-A),sbc=get_length(C-B);
 91         scd=get_length(D-C),sda=get_length(A-D);
 92 
 93         
 94         //求角度 
 95         double a,b,c,d;
 96         a=get_angle(D-A,B-A);
 97         b=get_angle(A-B,C-B);
 98         c=get_angle(B-C,D-C);
 99         d=get_angle(C-D,A-D);    
100         
101         
102         
103         printf("Case %d: ",++flag);
104         if(n<4)
105         {
106             printf("Ordinary Quadrilateral\n");
107             continue;
108         }
109     
110         if(dcmp(a-b)==0 && dcmp(b-c)==0 && dcmp(c-d)==0 && dcmp(d-a)==0 && dcmp(sab-sbc)==0 && dcmp(sbc-scd)==0 && dcmp(scd-sda)==0)
111         {
112             printf("Square\n");
113         }
114         else if(dcmp(a-b)==0 && dcmp(b-c)==0 && dcmp(c-d)==0 && dcmp(d-a)==0 && dcmp(sab-scd)==0 && dcmp(sda-sbc)==0)
115         {
116             printf("Rectangle\n");
117         }
118         else if(dcmp(sab-sbc)==0 && dcmp(sbc-scd)==0 && dcmp(scd-sda)==0&&dcmp(a-c)==0&&dcmp(b-d)==0)
119         {
120             printf("Rhombus\n");
121         }
122           else if(dcmp(sab-scd)==0 && dcmp(sbc-sda)==0&&dcmp(a-c)==0&&dcmp(b-d)==0)
123           {
124               printf("Parallelogram\n");
125           }
126           else if(dcmp(cross(B-A,C-D))==0 || dcmp(cross(C-B,D-A))==0)
127           {
128               printf("Trapezium\n");
129           }
130           else 
131           {
132               printf("Ordinary Quadrilateral\n");
133           }
134           
135     }
136     return 0;
137 }

最后贴一下这题的艰辛,我快累死了