题目大意:
求最远点对距离
求凸包上的最远点对
挑战263页
#include <cstdio> #include <string.h> #include <algorithm> #include <vector> #include <cmath> using namespace std; const int N=5e5+5; const double eps=1e-10; int n; 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); }; }p[N]; bool cmp(const P &a,const P &b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; } vector <P> andrew() { sort(p,p+n,cmp); int k=0; vector <P> q(n*2); for(int i=0;i<n;i++) { while(k>1 && (q[k-1]-q[k-2]).det(p[i]-q[k-1])<=0) k--; // >0时q[k-1]才位于线段q[k-2]p[i]的左侧 形成下凸 q[k++]=p[i]; } /// 求下凸 for(int i=n-2,t=k;i>=0;i--) { while(k>t && (q[k-1]-q[k-2]).det(p[i]-q[k-1])<=0) k--; q[k++]=p[i]; } /// 求上凸 q.resize(k-1); return q; } double dist(P a,P b) { return (a-b).dot(a-b); } // 点ab距离的平方 void solve() { vector <P> q=andrew(); int n=q.size(); if(n==2) { printf("%.0f ",dist(q[0],q[1])); return ; } int i=0, j=0; for(int k=0;k<n;k++) { if(!cmp(q[i],q[k])) i=k; // 凸包的最左下 if(cmp(q[j],q[k])) j=k; // 凸包的最右上 } double ans=0; int si=i, sj=j; while(i!=sj || j!=si) { // 转半圈就能判断到所有对踵点对 ans=max(ans,dist(q[i],q[j])); /*判断旋转 <0两者未达到平行 那么先转i更易达到平行 >0两者超过平行 那么转j更易达到平行 */ if((q[(i+1)%n]-q[i]).det(q[(j+1)%n]-q[j])<0) i=(i+1)%n; else j=(j+1)%n; } printf("%.0f ",ans); } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); solve(); return 0; }