Lifting the Stone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10753 Accepted Submission(s): 4499
参考博客:https://blog.csdn.net/lttree/article/details/24720007
求多边形重心分两种情况:
①质量集中在顶点上。n个顶点坐标为(xi,yi),质量为mi,则重心
X = ∑( xi×mi ) / ∑mi
Y = ∑( yi×mi ) / ∑mi
特殊地,若每个点的质量相同,则
X = ∑xi / n
Y = ∑yi / n
②质量分布均匀。这个题就是这一类型,算法和上面的不同。
特殊地,质量均匀的三角形重心:
X = ( x0 + x1 + x2 ) / 3
Y = ( y0 + y1 + y2 ) / 3
本题求质量分布均匀的多边形的重心,若将其转化为质量集中在顶点上的多边形,就可以套用第一种情况求重心了。所以把原多边形的n个顶点与坐标原点相连划分成n个三角形,这n个三角形是质量分布均匀的,其重心可以由第二种情况求出。将n个三角形的重心为顶点构成一个新的多边形,那么这个新的多边形的质量集中于顶点上,可以套用第一种情况求解,求出的新多边形重心即原多边形重心。
具体见注释:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int N = 1e6 + 20;
struct Point
{
double x, y;
///叉积
double operator ^ (const Point &b)const
{
return x * b.y - y * b.x;
}
}p[N];
///质量均匀多边形重心
Point bcenter(Point p[], int n)
{
Point res;
double sum = 0; ///多边形面积
double xx = 0, yy = 0; ///多边形重心坐标
for(int i = 0; i < n; ++i) ///将多边形划分成n个三角形
{
double tmp = (p[i] ^ p[(i + 1) % n]); ///三角形的面积的2倍
sum += tmp / 2; ///多边形的面积
///三角形的重心与质量加权(由于质量分布均匀,质量与面积成正比,故相当于面积)
///三角形的重心与质量(面积)相乘(重心横坐标实际为 X = (0 + p[1].x + p[2].x) / 3 三角形面积实际为tmp / 2 为了防止精度受损,暂且不进行除法)
xx += (p[i].x + p[(i + 1) % n].x) * tmp;
yy += (p[i].y + p[(i + 1) % n].y) * tmp;
}
///tmp / 2 重心坐标 / 3 故 / 6
res.x = xx / (6 * sum);
res.y = yy / (6 * sum);
return res;
}
int main()
{
int n, t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 0; i < n; ++i)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
}
Point ans = bcenter(p, n);
printf("%.2f %.2f\n", ans.x, ans.y);
}
return 0;
}