现在的位置: 首页 > 综合 > 正文

hdu 3694 费马点的应用

2013年02月12日 ⁄ 综合 ⁄ 共 1749字 ⁄ 字号 评论关闭

题目任意给出四个点,求出到这四个点的距离之和最小的点到这四个点的距离

若四边形为凸的,费马点为对角线交点,否则为凹的那点

证明很简单,把要证明的那点与其他顶点连起来,再任取一点,证明这点到四个顶点的距离比原来那点长即可

View Code

#include<stdio.h>
#include<math.h>
#include<string.h>
const double esp=1e-8;
struct point{
double x,y;
}a[10];
struct line
{
double a,b,c;
};
double min(double a,double b)
{
return a<b?a:b;
}
double dis(point a,point b)
{
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
int dblcmp(double d)
{
if(fabs(d)<esp)
return 0;
return (d>0)?1:-1;
}
double cross(point a, point b, point c)
{
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
void lineintersect(line l1,line l2, double &x, double &y)
{
double d=l1.a*l2.b-l2.a*l1.b;
x=(l2.c*l1.b-l1.c*l2.b)/d;
y=(l2.a*l1.c-l1.a*l2.c)/d;
}
void lineform(double x1,double y1,double x2,double y2, line &temp)//ax+by+c=0;
{
temp.a=y2-y1;
temp.b=x1-x2;
temp.c=x2*y1-x1*y2;
}
double dit[5];
int main()
{
int i,j;
double ans;
point fermat;
while(1)
{
bool flag=false;
for(i=1;i<=4;i++)
{
scanf("%lf%lf",&a[i].x,&a[i].y);
if(a[i].x!=-1||a[i].y!=-1)
flag=true;
}
if(!flag)
break;
memset(dit,0,sizeof(dit));
for(i=1;i<=4;i++)
{
for(j=1;j<=4;j++)
{
dit[i]+=dis(a[i],a[j]);
}
}
line temp1,temp2;
double fx,fy;
if(cross(a[1],a[2],a[3])*cross(a[1],a[2],a[4])<0)
{
lineform(a[1].x,a[1].y,a[2].x,a[2].y,temp1);
lineform(a[3].x,a[3].y,a[4].x,a[4].y,temp2);
lineintersect(temp1,temp2,fx,fy);
}
else if(cross(a[1],a[3],a[4])*cross(a[1],a[3],a[2])<0)
{
lineform(a[1].x,a[1].y,a[3].x,a[3].y,temp1);
lineform(a[2].x,a[2].y,a[4].x,a[4].y,temp2);
lineintersect(temp1,temp2,fx,fy);
}
else if(cross(a[1],a[4],a[3])*cross(a[1],a[4],a[2])<0)
{
lineform(a[1].x,a[1].y,a[4].x,a[4].y,temp1);
lineform(a[2].x,a[2].y,a[3].x,a[3].y,temp2);
lineintersect(temp1,temp2,fx,fy);
}
ans=0;
fermat.x=fx;fermat.y=fy;
for(i=1;i<=4;i++)
{
ans+=dis(fermat,a[i]);
}
double tans=min(min(dit[1],dit[2]),min(dit[3],dit[4]));
double ret=min(tans,ans);
printf("%.4lf\n",ret);
}
return 0;
}

抱歉!评论已关闭.