正方形的每个点都找出来,做凸包,距离最大的肯定都是凸包上的点,然后找対踵点对:先固定点u到u+1这条有向边,v到v+1的边从u到u+1的下一条边开始旋转,一直到两条边的叉积小于0,这个时候点 v 就是 u 的対踵点,如果叉积等于0 的话,v+1也是 u 的対踵点;找到u的対踵点之后就更新最大值,然后找u+1的対踵点。
(刘汝佳的模板)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-10;
struct Point
{
int x, y;
Point() {}
Point(int x, int y):x(x), y(y) {}
bool operator < (const Point& a) const
{
if (x == a.x)
return y < a.y;
return x < a.x;
}
bool operator == (const Point& a) const
{
return x == a.x && y == a.y;
}
};
typedef Point Vector;
Point P[400040], convex[400040];
Vector operator - (Point A, Point B)
{
return Vector(A.x-B.x, A.y-B.y);
}
int Cross(Vector A, Vector B)
{
return A.x*B.y - A.y*B.x;
}
int ConvexHull(Point *p, int n, Point *ch)
{
sort(p, p+n);
n = unique(p, p+n) - p;
int m = 0;
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--;
return m;
}
int dis(Point a, Point b)
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
int diameter(Point *convex, int n)
{
int ans = 0;
if (n == 1)
return 0;
if (n == 2)
return dis(convex[0],convex[1]);
for (int u=0, v=1; u<n; u++)
{
for (;;)
{
int k = Cross(convex[u+1]-convex[u], convex[v+1]-convex[v]);
if (k <= 0)
{
ans = max(ans, dis(convex[u],convex[v]));
if (k == 0)
ans = max(ans, dis(convex[u],convex[v+1]));
break;
}
v = (v+1) % n;
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while (t > 0)
{
t--;
int n;
int cnt = 0;
scanf("%d",&n);
for (int i=0; i<n; i++)
{
int x, y, w;
scanf("%d%d%d",&x, &y, &w);
P[cnt++] = Point(x,y);
P[cnt++] = Point(x, y+w);
P[cnt++] = Point(x+w, y);
P[cnt++] = Point(x+w, y+w);
}
int m = ConvexHull(P,cnt,convex);
printf("%d\n",diameter(convex, m));
}
return 0;
}