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 #include2 #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 }
最后贴一下这题的艰辛,我快累死了