【POJ 2187】 Beauty Contest (凸包-Graham扫描算法)

【POJ 2187】 Beauty Contest (凸包-Graham扫描算法)

找平面最远点对 数据很大 用暴力会T..我感觉……

扫描出个凸包 然后枚举凸包上的点即可 没坑 int也可过 注意重边跟共线就行 代码下附赠几组数据

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <stack>
#include <algorithm>
#define ll long long

using namespace std;

typedef struct Line Line;
typedef struct Point Point;

ll mx,my;

struct Point
{
    ll x,y;
    ll operator - (const Point a)const
    {
        return (x-a.x)*(x-a.x)+(y-a.y)*(y-a.y);
    }

    bool operator < (const Point a)const
    {
        if(x == mx && y == my) return false;
        if(a.x == mx && a.y == my) return true;
        if((x-mx)*(a.y-my) - (y-my)*(a.x-mx) == 0) return (x-mx)*(x-mx)+(y-my)*(y-my) < (a.x-mx)*(a.x-mx)+(a.y-my)*(a.y-my);
        return (x-mx)*(a.y-my) - (y-my)*(a.x-mx) > 0;
    }
};

struct Line
{
    ll x,y;
    bool operator > (const Line a)const//顺时针
    {
        return x*a.y - y*a.x > 0;
    }
};

Point pt[50000];
stack <Point> s;
vector <Point> tmp;

void Read(int &n)//输入并进行极角排序
{
    scanf("%d",&n);
    int mm = 0;
    for(int i = 0; i < n; ++i)
    {
        scanf("%lld %lld",&pt[i].x,&pt[i].y);
        if(pt[i].x < pt[mm].x || (pt[i].x == pt[mm].x && pt[i].y < pt[mm].y))
            mm = i;
    }
    mx = pt[mm].x;
    my = pt[mm].y;
    sort(pt,pt+n);
}

void SetTb(int n)//建凸包
{
    Point p1,p2;
    Line l1,l2;
    s.push(Point{mx,my});
    s.push(pt[0]);
    for(int i = 1; i < n; ++i)
    {
        if(pt[i].x == mx && pt[i].y == my) break;
        p2 = s.top();
        s.pop();
        while(!s.empty())
        {
            p1 = s.top();
            s.pop();
            l1.x = p2.x - p1.x;
            l1.y = p2.y - p1.y;
            l2.x = pt[i].x - p1.x;
            l2.y = pt[i].y - p1.y;
            if(l1 > l2)
            {
                s.push(p1);
                break;
            }
            p2 = p1;
        }
        s.push(p2);
        s.push(pt[i]);
    }
}

ll MaxLength()//从栈中不断出栈找最远点距
{
    int i;
    ll Maxlen = 0;
    while(!s.empty())
    {
        Point tp;
        tp = s.top();
        s.pop();
        for(i = 0; i < tmp.size(); ++i)
        {
            Maxlen = max(Maxlen,tp-tmp[i]);
        }
        tmp.push_back(tp);
    }
    return Maxlen;
}

int main()
{
    int n;
    Read(n);
    SetTb(n);
    printf("%lld\n",MaxLength());
    return 0;
}

/*
Input:
9
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200
4
0 0
0 1
0 1
0 0
2
0 0
0 1
Output:
130000
1
1
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 00:56:25

【POJ 2187】 Beauty Contest (凸包-Graham扫描算法)的相关文章

poj 2187 Beauty Contest——旋转卡壳

题目:http://poj.org/problem?id=2187 学习材料:https://blog.csdn.net/wang_heng199/article/details/74477738 https://www.jianshu.com/p/74c25c0772d6 可以再倒着枚举一遍那样求凸包. 用叉积算面积来旋转卡壳. 注意在面积等于的时候就不要往后走了,不然只有两个点的数据就会死循环. #include<cstdio> #include<cstring> #inclu

POJ 2187 Beauty Contest

题意: 题目链接 给定 \(n\) 个点,求距离最远的两个点之间的距离,输出最远距离的平方 \(n<=50000\) 思路: 旋转卡壳... 注意事项: 数组名称不要弄混了 code: #include<cstdio> #include<algorithm> using namespace std; const int N=50005; int n,top,per[N],res; struct point{int x,y;int dist(){return x*x+y*y;}

POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法

水平序 Graham 扫描算法: 计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种. 极角序算法能一次确定整个凸包, 但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较多. 水平序算法需要扫描两次,但排序简单,讨论简单,不易出错. [算法流程] 1.对顶点按x为第一关键字,y为第二关键字进行排序. 2.准备一个空栈,并将前两个点压入栈. 3.对于每一个顶点A,只要栈顶中还至少两个顶点,记栈顶为T,栈中第二个为U. 若UT(向量) * TA(向量) <= 0, 则将

凸包——Graham扫描法和Andrew算法

凸包:能围住所有给出的点的面积最小的多边形(个人理解) Graham:选取y值最小的点,将其它点极角排序,依次把1~n号点加入栈中,判断当前点.栈顶.栈顶下面那个点三者的关系(嘻嘻),一直这样做就好了 判断用叉积,也就是如下图的要判掉(top--) 其实上图是不对的哦,你有没有反应过来呢~按极角排序后不会有这种情况哦,肯定是先连a[i],再连s[top]的 具体实现看代码吧~ #include<cstdio> #include<cmath> #include<algorith

POJ2187 Beauty Contest (旋转卡壳算法 求直径)

POJ2187 旋转卡壳算法如图 证明:对于直径AB 必然有某一时刻 A和B同时被卡住 所以旋转卡壳卡住的点集中必然存在直径 而卡壳过程显然是O(n)的 故可在O(n)时间内求出直径 凸包具有良好的性质 其中的点是有序的 对于某个点 从它之后的点与它的距离必然是一个单峰凸函数 根据这个性质也可以设计一个O(nlogn)的算法 给出代码 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<

poj 3660 Cow Contest(warshall算法)

poj 3660 Cow Contest Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the co

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

计算几何 二维凸包问题 Andrew算法

凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把所有点排序,按照第一关键字x第二关键字y从小到大排序,删除重复点后得到点序列P1...Pn. 1)把P1,P2放入凸包中,凸包中的点使用栈存储 2)从p3开始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续: 3)否则依次删除最近加入凸包的点,直到新点在左边. 如图,新点P18在当前前进方向P10P15的右边(使用叉积判断),因此需要从凸包上删除点P15和P10

凸包-Graham扫描法

RT,Graham扫描法求凸包分为3步: 1.找到y最小的点 2.以y最小的点O为原点,求其余所有点相对O的极角并按极角从小到大排序 3.对于排序后的点集,配合栈,完成Graham扫描. ConvexHull.py #coding=utf-8 import math import numpy import pylab as pl #画原始图 def drawGraph(x,y): pl.title("The Convex Hull") pl.xlabel("x axis&qu