`
kmplayer
  • 浏览: 510044 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

国际大学生程序设计竞赛例题_4,1遥远的距离

阅读更多
1,题意:y轴左右两个点集,求它们中点的最远距离.
2,解决:
最远距离的两个点必定在所有点的凸包上,点到点的最远距离对应点相关的凸包边到点的最远距离.
先求出凸包点,在依次求出每条凸包边对应的最远点,得到一个ans,遍历所有的边即可得到结果.
3,实现代码:
#include <iostream>
#include <cmath>
using namespace std;

/*
PointSet[]:输入的点集
ch[]:输出的凸包上的点集,按照逆时针方向排列
n:PointSet中的点的数目
len:输出的凸包上的点的个数
*/

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;
}

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
//返回值点q到线段p1p2的距离
double pointToLine(Point p1,Point p2,Point q)
{
    int flag=1;
    double k;
    Point s;
    if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;}
    if (p1.y==p2.y) {s.x=q.x;s.y=p1.y;flag=0;}
    if (flag)
    {
        k=(p2.y-p1.y)/(p2.x-p1.x);
        s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);
        s.y=k*(s.x-p1.x)+p1.y;
    }
    if (MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))
        return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));
    else
        return MIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2.y)*(q.y-p2.y)));
}


const int maxN=200000;
Point PointSet[maxN];
Point ch[maxN];
int n;//记录点的个数
int len;//记录凸包的点数
double ans;//结果

//求出两两点之间的最远距离
void check(Point p1,Point p2)
{
    if( (p1.x<0)!=(p2.x<0) )//保证p1和p2在不同的点集
    {
        double tmp=dis(p1,p2);
        if(tmp>ans) ans=tmp;
    }
}

int main()
{
    freopen("4.1.in","r",stdin);
    cout.setf(ios::fixed);
    cout.precision(3);
    int cnt;
    int numa,numb;//两个点集的大小
    cin>>cnt;
    while(cnt--)
    {
        ans=0;
        n=0;
        cin>>numa>>numb;
        while(numa--) cin>>PointSet[n].x>>PointSet[n].y,n++;
        while(numb--) cin>>PointSet[n].x>>PointSet[n].y,n++;
        Graham_scan(PointSet,ch,n,len);//返回凸包点,保存到ch
        double tmp1,tmp2;
        int i,j=1;
        //寻找每个点所在凸包边到点的最远距离
        //间接得到点到点的最远距离
        for(i=0;i<len;i++)
        {
            //距离先增加,后降,拐点就是最远的那个点
            while(1)
            {
                tmp1=pointToLine(ch[i],ch[(i+1)%len],ch[j]);
                tmp2=pointToLine(ch[i],ch[(i+1)%len],ch[(j+1)%len]);
                if(tmp1<=tmp2) break;
            }
            j=(j+1)%len;
            check(ch[i],ch[j]);
            check(ch[i+1],ch[j]);
            check(ch[i],ch[j+1]);
            check(ch[i+1],ch[j+1]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

分享到:
评论

相关推荐

    国际大学生程序设计竞赛例题解.一:数论、计算几何、搜索算法专集.

    国际大学生程序设计竞赛(ICPC)是全球范围内极具影响力的编程竞赛,旨在培养大学生的创新思维和团队合作能力,同时也对参赛者的算法理解与实现能力提出了极高的要求。本压缩包中的资源聚焦于数论、计算几何和搜索...

    算法参考资料国际大学生程序设计竞赛例题解4广东省信息学奥林匹克竞赛试题2003-2006年

    总之,这份《算法参考资料国际大学生程序设计竞赛例题解 4 广东省信息学奥林匹克竞赛试题 2003-2006年》对于想要提升算法竞赛能力的学习者来说是一份非常宝贵的资料。通过研究这些例题,参赛者可以系统地学习和掌握...

    算法参考资料国际大学生程序设计竞赛例题解3图论·动态规划算法·综合题专集

    这份资料集中的标题揭示了内容的几个关键点,即它是一份专门为解决算法问题而编写的参考资料,特别针对国际大学生程序设计竞赛(ICPC)或者类似的算法竞赛中的例题。 首先,从“图论”这一关键词来看,我们可以推断...

    ACM竞赛网络流算法讲义

    的学科在信息技术领域中扮演着至关重要的角色,网络流算法是图论的一个重要分支,它在计算机科学,尤其是算法竞赛如ACM(国际大学生程序设计竞赛)中有着广泛的应用。网络流问题通常涉及到在一个有向图中从源点到...

    acm.rar_ACM

    在ACM(国际大学生程序设计竞赛)中,动态规划(Dynamic Programming, 简称DP)是一种非常重要的算法思想,它被广泛应用于解决各种复杂问题,尤其在优化问题和组合问题中表现出色。本压缩包“acm.rar_ACM”显然是...

    刘汝佳ACM讲义很不错的资料

    刘汝佳,作为中国计算机竞赛领域的一位知名教练和学者,他的ACM讲义深受学习者欢迎,尤其对于那些致力于参与ACM国际大学生程序设计竞赛(ICPC)的学生而言,这些讲义是不可多得的学习资源。ACM竞赛,全称Association...

    ACM新生课件

    - **ICPC**: International Collegiate Programming Contest,国际大学生程序设计竞赛,由ACM主办的一项国际性赛事,旨在提升学生解决实际问题的能力和团队合作精神。 #### 二、ICPC比赛规则及赛程安排 - **比赛...

Global site tag (gtag.js) - Google Analytics