codeforces 23D Tetragon 计算几何
题意:给你三条相等的边的中点,问是否存在这样的凸四边形
思路:因为答案是四边形,所以这三条边肯定是连续的,我们枚举中间那条边。
不妨设中间的边的两个端点分别为p和q,其中点为b,相邻两边的中点为a和c。
则显然,p必须在线段ab的垂直平分线上,q必须在线段bc的垂直平分线上。
#include <iostream> #include <math.h> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define eps 1e-8 struct point { double x,y; point() { x=y=0; } point(double xx,double yy) { x=xx; y=yy; } } p[3],ans[4],w[4]; int top; double dist(point a,point b) { return hypot(fabs(a.x-b.x),fabs(a.y-b.y)); } double Mul(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } int cmp(const void *a,const void *b) { point c=*(point *)a; point d=*(point *)b; double k=Mul(ans[0],c,d); if(k<0||(!k&&dist(c,ans[0])>dist(d,ans[0]))) return 1; return -1; } //凸包模板 void con() { int i; int n=4; for(i=1;i<n;i++) { point temp; if(ans[i].y<ans[0].y||(ans[i].y==ans[0].y&&ans[i].x<ans[0].x)) { temp=ans[i]; ans[i]=ans[0]; ans[0]=temp; } } qsort(ans+1,n-1,sizeof(ans[0]),cmp); w[0]=ans[0]; w[1]=ans[1]; w[2]=ans[2]; top=2; for(i=3;i<n;i++) { while(top>=2&&Mul(w[top-1],w[top],ans[i])<=0) top--; top++; w[top]=ans[i]; } } bool TB() { top=0; con(); int i,j,k; if(top==3) { for(i=0;i<=3;i++) { for(j=0;j<=3;j++) { for(k=0;k<=3;k++) { if(i==j||i==k||j==k) continue; //三点不在一条直线上 if(fabs((w[j].y-w[i].y)*(w[j].x-w[k].x)-(w[j].y-w[k].y)*(w[j].x-w[i].x))<eps) return 0; } } } double dis[5]; for(i=0;i<4;i++) dis[i]=dist(w[i],w[(i+1)%4]); sort(dis,dis+4); int tp1=0,tp2=0; for(i=0;i<4;i++) { if(fabs(dis[i]-dis[0])<eps) tp1++; if(fabs(dis[i]-dis[3])<eps) tp2++; } if(tp1>=3||tp2>=3) return 1; return 0; } return 0; } int solve(point b,point a,point c) { double k1,k2; point d=point((a.x+b.x)/2,(a.y+b.y)/2); point e=point((c.x+b.x)/2,(c.y+b.y)/2); if(fabs(a.y-b.y)<eps) { if(fabs(c.y-b.y)<eps) return 0; else { k2=-(c.x-b.x)/(c.y-b.y); double uy=-(k2*(2*b.x-d.x-e.x)+e.y-2*b.y); ans[0]=point(d.x,uy); ans[1]=point(2*b.x-d.x,2*b.y-uy); ans[2]=point(2*c.x-ans[1].x,2*c.y-ans[1].y); ans[3]=point(2*a.x-ans[0].x,2*a.y-ans[0].y); return TB(); } } else { k1=-(a.x-b.x)/(a.y-b.y); if(fabs(c.y-b.y)<eps) { double ux=2*b.x-e.x; ans[0]=point(ux,k1*(ux-d.x)+d.y); ans[1]=point(2*b.x-ux,2*b.y-k1*(ux-d.x)-d.y); ans[2]=point(2*c.x-ans[1].x,2*c.y-ans[1].y); ans[3]=point(2*a.x-ans[0].x,2*a.y-ans[0].y); return TB(); } else { k2=-(c.x-b.x)/(c.y-b.y); if(fabs(k1-k2)<eps) return 0; double ux=-k1*d.x+2*k2*b.x-k2*e.x+e.y+d.y-2*b.y; ux/=(k2-k1); ans[0]=point(ux,k1*(ux-d.x)+d.y); ans[1]=point(2*b.x-ux,2*b.y-k1*(ux-d.x)-d.y); ans[2]=point(2*c.x-ans[1].x,2*c.y-ans[1].y); ans[3]=point(2*a.x-ans[0].x,2*a.y-ans[0].y); return TB(); } } } int main() { int T,i,j,k,m,n,flag; point a,b,c; scanf("%d",&T); while(T--) { for(i=0; i<3; i++) scanf("%lf%lf",&p[i].x,&p[i].y); flag=0; for(i=0; i<3; i++) { b=p[i]; a=p[(i+1)%3]; c=p[(i+2)%3]; if(solve(b,a,c)) { flag=1; break; } } if(flag) { printf("YES\n"); for(i=0; i<4; i++) printf("%.10f %.10f ",w[i].x,w[i].y); printf("\n"); } else printf("NO\n\n"); } return 0; }