HDU 3694 Fermat Point in Quadrangle (费马定理求四边形的费马点)

题意:给你四个点,找出一个点到四个点的距离最小

四边形的费马点:凸边形是两对角线的交点,凹边形式凹点。

PS:

三角形的费马点:

1.若三角形3个内角均小于120°,那么3条距离连线正好三等分费马点所在的周角,即该点所对三角形三边的张角相等,均为120°。所以三角形的费马点也称为三角形的等角中心。

2.若三角形有一内角大于等于120°,则此钝角的顶点就是距离和最小的点。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<string>
#include<queue>
#include<map>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int kind = 26;
const int maxn = 250*1000; //注意RE,单词长度*单词个数
const int M = 5100000;
struct Point
{
    double x,y;
};
//小于0,说明向量p0p1的极角大于p0p2的极角
double multiply(Point p1,Point p2,Point p0)
{
    return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}    

double dis(Point p1,Point p2)
{
    return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
void Graham_scan(Point PointSet[],Point ch[],int n,int &len)
{
    int i,j,k=0,top=2;
    Point tmp;    

    //找到最下且偏左的那个点
    for(i=1;i<n;i++)
        if ((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<PointSet[k].x)))
            k=i;
    //将这个点指定为PointSet[0]
    tmp=PointSet[0];
    PointSet[0]=PointSet[k];
    PointSet[k]=tmp;    

    //按极角从小到大,距离偏短进行排序
    for (i=1;i<n-1;i++)
    {
        k=i;
        for (j=i+1;j<n;j++)
            if( (multiply(PointSet[j],PointSet[k],PointSet[0])>0)
                ||((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
                    &&(dis(PointSet[0],PointSet[j])<dis(PointSet[0],PointSet[k]))) )
                k=j;//k保存极角最小的那个点,或者相同距离原点最近
        tmp=PointSet[i];
        PointSet[i]=PointSet[k];
        PointSet[k]=tmp;
    }
    //第三个点先入栈
    ch[0]=PointSet[0];
    ch[1]=PointSet[1];
    ch[2]=PointSet[2];
    //判断与其余所有点的关系
    for (i=3;i<n;i++)
    {
        //不满足向左转的关系,栈顶元素出栈
        while(multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;
        //当前点与栈内所有点满足向左关系,因此入栈.
        ch[++top]=PointSet[i];
    }
    len=top+1;
}
Point intersection(Point u1,Point u2,Point v1,Point v2)
{
    Point ret=u1;
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
        /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x+=(u2.x-u1.x)*t;
    ret.y+=(u2.y-u1.y)*t;
    return ret;
}
Point p[4],ch[4],point;
int len;
int main()
{
    int x1, y1, x2, y2, x3, y3, x4, y4;
    int x[4],y[4];
    while(scanf("%lf%lf",&p[0].x,&p[0].y))
    {
        int flag=0;
        if(p[0].x!=-1||p[0].y!=-1) flag=1;
        for(int i=1;i<4;i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);
            if(p[i].x!=-1||p[i].y!=-1)
                flag=1;
        }
        if(!flag) break;
        double minn=10000000,ans=0.0;
        int k=0;
        Graham_scan(p,ch,4,len);
        for(int i=0;i<4;i++)
        {
            ans=0.0;
            for(int j=0;j<4;j++)
            {
                ans+=dis(p[i],p[j]);
            }
            if(ans<minn)
                minn=ans;
        }
        point=intersection(p[0],p[2],p[1],p[3]);
        //printf("%lf %lf\n",point.x,point.y);
        ans=0.0;
        for(int i=0;i<4;i++)
        {
            ans+=dis(p[i],point);
        }
        printf("%.4lf\n",min(minn,ans));
    }
    return 0;
}
/*
0 0 0 0 1 0 0 1
0 0 1 1 1 0 0 1
1 1 1 1 1 1 1 1
-1 -1 -1 -1 -1 -1 -1 -1
*/

HDU 3694 Fermat Point in Quadrangle (费马定理求四边形的费马点)

时间: 2024-08-06 20:06:56

HDU 3694 Fermat Point in Quadrangle (费马定理求四边形的费马点)的相关文章

Hdu 3694 Fermat Point in Quadrangle(三分)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3694 思路:三分竟然能水过....感觉不是很对.... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const double eps=1e-7; struct Node { double x,y; }; Node a[

HDU3694 Fermat Point in Quadrangle(求四边形费马点)

题意:给个四边形,问一个点到四边形四个点距离最小的距离和是多少. 分析:如果是凸四边形,费马点就是对角线的交点,距离就是对角线长度. 如果是凹多边形,费马点就是那个凹点. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<cstdlib> #include<queue> #inclu

hdu3694 Fermat Point in Quadrangle 求四边形费马点

http://acm.hdu.edu.cn/showproblem.php?pid=3694 Fermat Point in Quadrangle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1973    Accepted Submission(s): 361 Problem Description In geometry the

HDU 2440、HDU 3694多边形费马点

1.http://acm.hdu.edu.cn/showproblem.php?pid=2440   按照题意知道是一个简单的多边形即凸包,但给出的点并没有按照顺序的,所以需要自己先求出凸包,然后在用随机淬火求费马点. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<cstdlib> #inc

poj 3990 Fermat Point in Quadrangle 凸包和费马点

题意: 求一个四边形的费马点. 分析: 模拟退火要么超时要么wa,这题的数据就是不想让随机算法过的..其实四边形的费马点很简单,如果是凸四边形的话费马点是对角线交点,如果是凹四边形费马点是凹点.但题目给的四个点顺序是不确定的,所以要先求下凸包. 代码: //poj 3990 //sep9 #include <iostream> #include <cmath> #include <algorithm> using namespace std; struct Point

HDU 4405 Aeroplane chess (概率DP求期望)

题意:有一个n个点的飞行棋,问从0点掷骰子(1~6)走到n点需要步数的期望 其中有m个跳跃a,b表示走到a点可以直接跳到b点. dp[ i ]表示从i点走到n点的期望,在正常情况下i点可以到走到i+1,i+2,i+3,i+4,i+5,i+6 点且每个点的概率都为1/6 所以dp[i]=(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])/6  + 1(步数加一). 而对于有跳跃的点直接为dp[a]=dp[b]; #include<stdio.h>

HDU 1517 A Multiplication Game (博弈-求sg)

A Multiplication Game Problem Description Stan and Ollie play the game of multiplication by multiplying an integer p by one of the numbers 2 to 9. Stan always starts with p = 1, does his multiplication, then Ollie multiplies the number, then Stan and

hdu how many prime numbers 筛选法求素数

/* * hdu How many prime numbers * date 2014/5/13 * state AC */ #include <iostream> #include <cmath> #include <cstdio> using namespace std; bool isPrime(int x) { int sqr=sqrt(x*1.0); for(int i=2;i<=sqr;i++) { if(x%i==0)return false; }

hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。

题意:求一个无向图的,去掉两个不同的点后最多有几个连通分量. 思路:枚举每个点,假设去掉该点,然后对图求割点后连通分量数,更新最大的即可.算法相对简单,但是注意几个细节: 1:原图可能不连通. 2:有的连通分量只有一个点,当舍去该点时候,连通分量-1: 复习求割点的好题! #include<iostream> #include<cstdio> #include<vector> using namespace std; int n,m; vector<vector&