【OI康复训练】POJ2187旋转卡壳

随便写一个旋转卡壳,结果有重复点实在是日了狗了

#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;

struct Point {
  int x, y;
  Point(int x=0, int y=0):x(x),y(y) { }
};
typedef Point Vector;
Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }
int Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; }
int Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y; }
int Dist2(const Point& A, const Point& B) { return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); }
bool operator < (const Point& p1, const Point& p2) { return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); }
bool operator == (const Point& p1, const Point& p2) { return p1.x == p2.x && p1.y == p2.y; }
vector<Point> ConvexHull(vector<Point>& p) {
  sort(p.begin(), p.end());
  p.erase(unique(p.begin(), p.end()), p.end());

  int n = p.size();
  int m = 0;
  vector<Point> ch(n+1);
  for(int i = 0; i < n; i++) {
    while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
    ch[m++] = p[i];
  }
  int k = m;
  for(int i = n-2; i >= 0; i--) {
    while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
    ch[m++] = p[i];
  }
  if(n > 1) m--;
  ch.resize(m);
  return ch;
}

int diameter2(vector<Point>& points) {
  vector<Point> p = ConvexHull(points);
  int n = p.size();
  if(n == 1) return 0;
  if(n == 2) return Dist2(p[0], p[1]);
  p.push_back(p[0]);
  int ans = 0;
  for(int u = 0, v = 1; u < n; u++) {
    for(;;) {
      int diff = Cross(p[u+1]-p[u], p[v+1]-p[v]);
      if(diff <= 0) {
        ans = max(ans, Dist2(p[u], p[v]));
        if(diff == 0) ans = max(ans, Dist2(p[u], p[v+1]));
        break;
      }
      v = (v + 1) % n;
    }
  }
  return ans;
}

int main() {
  int T=1;
  while(T--) {
    int n;
    scanf("%d", &n);
    vector<Point> points;
    for(int i = 0; i < n; i++) {
      int x, y;
      scanf("%d%d", &x, &y);
      points.push_back(Point(x, y));
    }
    printf("%d\n", diameter2(points));
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值