题意:求所有正方形中两点距离最大值的平方值。
思路:旋转卡壳法。
分别用数组和vector存凸包时,旋转卡壳代码有所不同。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<memory.h>
#include<cstdlib>
#include<vector>
#define clc(a,b) memset(a,b,sizeof(a))
#define LL long long int
#define up(i,x,y) for(i=x;i<=y;i++)
#define w(a) while(a)
using namespace std;
const double inf=0x3f3f3f3f;
const int N = ;
const double eps = *1e-;
const double PI = acos(-1.0);
using namespace std; struct Point
{
int x, y;
Point(int x=, int y=):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 = ;
vector<Point> ch(n+);
for(int i = ; i < n; i++)
{
while(m > && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-; i >= ; i--)
{
while(m > k && Cross(ch[m-]-ch[m-], p[i]-ch[m-]) <= ) m--;
ch[m++] = p[i];
}
if(n > ) m--;
ch.resize(m);
return ch;
} // 返回点集直径的平方
int diameter2(vector<Point>& points)
{
vector<Point> p = ConvexHull(points);
int n = p.size();
if(n == ) return ;
if(n == ) return Dist2(p[], p[]);
p.push_back(p[]); // 免得取模
int ans = ;
for(int u = , v = ; u < n; u++)
{
// 一条直线贴住边p[u]-p[u+1]
for(;;)
{
// 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v])时停止旋转
// 即Cross(p[u+1]-p[u], p[v+1]-p[u]) - Cross(p[u+1]-p[u], p[v]-p[u]) <= 0
// 根据Cross(A,B) - Cross(A,C) = Cross(A,B-C)
// 化简得Cross(p[u+1]-p[u], p[v+1]-p[v]) <= 0
int diff = Cross(p[u+]-p[u], p[v+]-p[v]);
if(diff <= )
{
ans = max(ans, Dist2(p[u], p[v])); // u和v是对踵点
if(diff == ) ans = max(ans, Dist2(p[u], p[v+])); // diff == 0时u和v+1也是对踵点
break;
}
v = (v + ) % n;
}
}
return ans;
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
vector<Point> points;
for(int i = ; i < n; i++)
{
int x, y, w;
scanf("%d%d%d", &x, &y, &w);
points.push_back(Point(x, y));
points.push_back(Point(x+w, y));
points.push_back(Point(x, y+w));
points.push_back(Point(x+w, y+w));
}
printf("%d\n", diameter2(points));
}
return ;
}