POJ 2187 —— 凸包 + 旋轉卡殼 求多邊形的直徑

Beauty Contest
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 25248   Accepted: 7752

Description

Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill between farmers and their cows. For simplicity, the world will be represented as a two-dimensional plane, where each farm is located at a pair of integer coordinates (x,y), each having a value in the range -10,000 ... 10,000. No two farms share the same pair of coordinates. 

Even though Bessie travels directly in a straight line between pairs of farms, the distance between some farms can be quite large, so she wants to bring a suitcase full of hay with her so she has enough food to eat on each leg of her journey. Since Bessie refills her suitcase at every farm she visits, she wants to determine the maximum possible distance she might need to travel so she knows the size of suitcase she must bring.Help Bessie by computing the maximum distance among all pairs of farms. 

Input

* Line 1: A single integer, N 

* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm 

Output

* Line 1: A single integer that is the squared distance between the pair of farms that are farthest apart from each other. 

Sample Input

4
0 0
0 1
1 1
1 0

Sample Output

2

Hint

Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2) 

Source

題意是給你n個點,求他們之間距離最遠的兩個點的座標

求多邊形直徑的模版題。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
using namespace std;
///#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 50000 + 50;
const int MAXS = 10000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
const int inf = 1 << 30;
#define eps 1e-10
const long long MOD = 1000000000 + 7;
const int mod = 10007;
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pii;
typedef vector<int> vec;
typedef vector<vec> mat;


#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")
///考慮誤差的加法運算
double add(double a , double b)
{
    if(abs(a + b) < eps * (abs(a) + abs(b)))return 0;
    return a + b;
}
///二維向量結構體
struct P
{
    double x , y;
    P(){}
    P(double x , double y) : x(x) , y(y){}
    P operator + (P p)
    {
        return P(add(x , p.x) , add(y , p.y));
    }
    P operator - (P p)
    {
        return P(add(x , - p.x) , add(y , - p.y));
    }
    P operator * (double d)
    {
        return P(x * d , y * d);
    }
    double dot(P p)///點乘
    {
        return add(x * p.x  , y * p.y);
    }
    double det(P p)///叉乘
    {
        return add(x * p.y , - y * p.x);
    }
};
///判斷點q是否在線段p1-p2上
bool on_seg(P p1 , P p2 , P q)
{
    return (p1 - q).det(p2 - q) == 0 && (p1 - q).dot(p2 - q) <= 0;
}
///計算直線p1-p2與直線q1-q2的交點座標
P intersection(P p1 , P p2 , P q1 , P q2)
{
    return p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1));
}
///字典序比較
bool cmp_x(const P& p , const P& q)
{
    if(p.x != q.x)return p.x < q.x;
    return p.y < q.y;
}
///求凸包
vector<P> convex_hull(P* ps , int n)
{
    sort(ps , ps + n , cmp_x);
    int k = 0;///凸包頂點數
    vector<P> qs(n * 2);///構造中的凸包
    ///構造凸包的下側
    for(int i = 0 ; i < n ; i++)
    {
        while(k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)k--;
        qs[k++] = ps[i];
    }
    ///構造凸包的上側
    for(int i = n - 2 , t = k ; i >= 0 ; i--)
    {
        while(k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0)k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}
///距離的平方
double dist(P p , P q)
{
    return (p - q).dot(p - q);
}
int n;
P ps[MAXN];
///旋轉卡殼
void solve()
{
    vector<P> qs = convex_hull(ps , n);
    int n = qs.size();
    if(n == 2)///特別處理凸包退化的情況
    {
        printf("%.0f\n" , dist(qs[0] , qs[1]));
        return ;
    }
    int i = 0, j = 0;
    for(int k = 0  ; k < n ; k++)
    {
        if(!cmp_x(qs[i] , qs[k]))i = k;///最右(上)點的序號
        if(cmp_x(qs[j] , qs[k]))j = k;///最左(下)點的序號
    }
    double res = 0;
    int si = i , sj = j;
    while(i != sj || j != si)///直到旋轉180度
    {
        res = max(res , dist(qs[i] , qs[j]));
        ///判斷先轉到邊i——(i + 1)的法線方向還是邊j——(j + 1)的法線方向
        if((qs[(i + 1) % n] - qs[i]).det(qs[(j + 1) % n] - qs[j]) < 0)
        {
            i = (i + 1) % n;
        }
        else j = (j + 1) % n;
    }
    printf("%.0f\n" , res);
}
int main()
{
    while(~scanf("%d" , &n))
    {
        for(int i = 0 ; i < n ; i++)scanf("%lf%lf" , &ps[i].x , &ps[i].y);
        solve();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章