您的位置:首页 > 编程语言 > Go语言

codeforces 23D Tetragon 计算几何

2016-03-28 14:20 411 查看
题意:给你三条相等的边的中点,问是否存在这样的凸四边形

思路:因为答案是四边形,所以这三条边肯定是连续的,我们枚举中间那条边。

不妨设中间的边的两个端点分别为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: