知识点 - 多边形的重心、核、三角形的心
解决问题类型:
多边形的重心。
三角形的内、外、垂心。
三角形的费马点(到三点和距离最小)
复杂度与代码:
O(n)n为点数
多边形重心
即过这点的直线平分该多边形
#include <stdio.h>
#include <math.h>
int x[1000003], y[1000003];
double A, tx, ty, tmp;
int main (void)
{
int cases, n, i;
scanf ("%d", &cases);
while (cases --)
{
scanf ("%d", &n);
A = 0.0;
x[0] = y[0] = 0;
for (i = 1; i <= n; i ++)
{
scanf ("%d %d", &x[i], &y[i]);
A += (x[i-1]*y[i] - x[i]*y[i-1]);
}
A += x[n]*y[1] - x[1]*y[n];
A = A / 2.0;
tx = ty = 0.0;
for (i = 1; i < n; i ++)
{
tmp = x[i]*y[i+1] - x[i+1]*y[i];
tx += (x[i]+x[i+1]) * tmp;
ty += (y[i]+y[i+1]) * tmp;
}
tmp = x[n]*y[1] - x[1]*y[n];
tx += (x[n]+x[1])*tmp;
ty += (y[n]+y[1])*tmp;
printf ("%.2lf %.2lf\n", tx/(6.0*A), ty/(6.0*A));
}
return 0;
}
多边形是否有核
星形多边形是什么呢?其实就是在多边形内部存在一个点A,这个点与多边形内任意一点的连线都在多边形内部,就叫做星形多边形,这一个点A就叫做多边形的内核。
多边形的核可以这样理解:这个核为原多边形内部的一个多边形,站在这个叫核的多边形中,我们能看到原多边形的任何一个位置。
#include <stdio.h>
#include <string.h>
const int INF = (1<<30);
struct Point
{
int x, y;
}pt[150];
typedef struct Point Point;
bool turn_right[150];
int det(Point s1, Point t1, Point s2, Point t2)
{
int d1x = t1.x-s1.x;
int d1y = t1.y-s1.y;
int d2x = t2.x-s2.x;
int d2y = t2.y-s2.y;
return d1x*d2y - d2x*d1y;
}
void Swap(int &a, int &b)
{
if (a>b)
{
int t=a;
a=b;
b=t;
}
}
int main (void)
{
int n, i, cross, maxx, minx, maxy, miny, maxn, minn, countn=0;
while (scanf("%d", &n)==1&&n)
{
maxx=maxy=-INF;
minx=miny=INF;
//点按顺时针给出
for (i=1; i<=n; i++)
{
scanf("%d %d", &pt[i].x, &pt[i].y);
if (maxx<pt[i].x) maxx=pt[i].x;
if (maxy<pt[i].y) maxy=pt[i].y;
if (minx>pt[i].x) minx=pt[i].x;
if (miny>pt[i].y) miny=pt[i].y;
}
pt[n+1]=pt[1];
pt[n+2]=pt[2];
pt[n+3]=pt[3];
pt[n+4]=pt[4];
//求每条线段的转向
for (i=1; i<=n+1; i ++)
{
cross = det(pt[i],pt[i+1], pt[i+1], pt[i+2]);
if (cross<0)
turn_right[i+1]=true;
else turn_right[i+1]=false;
}
//两条边连续右转的为凸处,只有此时才可影响“核”肯恩存在的范围
for (i=2; i<= n+1; i++)
if (turn_right[i] && turn_right[i+1])
{
if (pt[i].x==pt[i+1].x)
{
minn=pt[i].y;
maxn=pt[i+1].y;
Swap(minn, maxn);
if (minn>miny) miny=minn;
if (maxn<maxy) maxy=maxn;
}
else
{
minn=pt[i].x;
maxn=pt[i+1].x;
Swap(minn, maxn);
if (minn>minx) minx=minn;
if (maxn<maxx) maxx=maxn;
}
}
if (minx<=maxx && miny<=maxy)
printf("Floor #%d\nSurveillance is possible.\n\n", ++countn);
else printf("Floor #%d\nSurveillance is impossible.\n\n", ++countn);
}
return 0;
}
三角形的内外垂心
//定义点
struct point
{
double x, y;
};
typedef struct point point;
//定义直线
struct line
{
point a, b;
};
typedef struct line line;
//两点距离
double distance(point p1, point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
//两直线求交点
point intersection(line u, line v)
{
point ret = u.a;
double t = ((u.a.x - v.a.x)*(v.a.y - v.b.y) - (u.a.y - v.a.y)*(v.a.x - v.b.x))
/ ((u.a.x - u.b.x)*(v.a.y - v.b.y) - (u.a.y - u.b.y)*(v.a.x - v.b.x));
ret.x += (u.b.x - u.a.x)*t;
ret.y += (u.b.y - u.a.y)*t;
return ret;
}
//求三角形的外心
point circumcenter(point a, point b, point c)
{
line u, v;
u.a.x = (a.x + b.x) / 2;
u.a.y = (a.y + b.y) / 2;
u.b.x = u.a.x - a.y + b.y;
u.b.y = u.a.y + a.x - b.x;
v.a.x = (a.x + c.x) / 2;
v.a.y = (a.y + c.y) / 2;
v.b.x = v.a.x - a.y + c.y;
v.b.y = v.a.y + a.x - c.x;
return intersection(u, v);
}
//求三角形内心
point incenter(point a, point b, point c)
{
line u, v;
double m, n;
u.a = a;
m = atan2(b.y - a.y, b.x - a.x);
n = atan2(c.y - a.y, c.x - a.x);
u.b.x = u.a.x + cos((m + n) / 2);
u.b.y = u.a.y + sin((m + n) / 2);
v.a = b;
m = atan2(a.y - b.y, a.x - b.x);
n = atan2(c.y - b.y, c.x - b.x);
v.b.x = v.a.x + cos((m + n) / 2);
v.b.y = v.a.y + sin((m + n) / 2);
return intersection(u, v);
}
//求三角形垂心
point perpencenter(point a, point b, point c)
{
line u, v;
u.a = c;
u.b.x = u.a.x - a.y + b.y;
u.b.y = u.a.y + a.x - b.x;
v.a = b;
v.b.x = v.a.x - a.y + c.y;
v.b.y = v.a.y + a.x - c.x;
return intersection(u, v);
}
费马点
模拟退火板题
//计算三角形费马点
//返回:到三角形三顶点距离之和最小的点
Point fermentPoint()
{
Point u, v;
double step = fabs(a.x) + fabs(a.y) + fabs(b.x) + fabs(b.y) + fabs(c.x) + fabs(c.y);
int i, j, k;
u.x = (a.x + b.x + c.x) / 3;
u.y = (a.y + b.y + c.y) / 3;
while (step > eps)
{
for (k = 0; k < 10; step /= 2, k ++)
{
for (i = -1; i <= 1; i ++)
{
for (j =- 1; j <= 1; j ++)
{
v.x = u.x + step * i;
v.y = u.y + step * j;
if (getdis(u,a) + getdis(u,b) + getdis(u,c) > getdis(v,a) + getdis(v,b) + getdis(v,c))
u = v;
}
}
}
}
return u;
}