【日常训练】【CF】20200608_干扰_CF575E_计算几何

题面

题解

现场得分:85/100

因为我一开始加边的时候,打错了16个坐标之一。

  • 这题实在没什么的
  • 我们发现每一个碎片的范围都是一个多边形,我们最终的三角形的顶点总归在某一个多边形的顶点上,总归会有一个三角形覆盖了所有多边形。
  • 所以那个期望其实就是假的,你现在只要求覆盖了所有多边形的最大的外接圆。
  • 我们发现三个顶点肯定都在所有多边形的所有顶点组成的凸包上
  • 我们又发现三个顶点一定是在凸包上连续的
  • 我们还发现满足上述要求的最大的外接圆一定覆盖了整个凸包(这个我当时没有证出来,但是我认为它是对的)
  • 事实上,外接圆半径用正弦定理求最简单

代码

#include<bits/stdc++.h>
#define LL long long
#define eps 0.00000000001
#define MAXAI 100000
#define MAXN 100000
#define double long double
using namespace std;
template<typename T>void Read(T &cn)
{
	char c; int sig = 1;
	while(!isdigit(c = getchar())) if(c == '-') sig = -1; cn = c-48;
	while(isdigit(c = getchar())) cn = cn*10+c-48; cn*=sig;
}
template<typename T>void Write(T cn)
{
	if(cn < 0) {putchar('-'); cn = 0-cn; }
	int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
	while(cn) wei++, cm = cm*10+cn%10, cn/=10;
	while(wei--) putchar(cm%10+48), cm /= 10;
	putchar(cx+48);
}
template<typename T>void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
template<typename T>void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
struct dian2{
	double x,y;
	inline friend dian2 operator +(dian2 a, dian2 b) {dian2 guo; guo.x = a.x+b.x; guo.y = a.y+b.y; return guo; }
	inline friend dian2 operator -(dian2 a, dian2 b) {dian2 guo; guo.x = a.x-b.x; guo.y = a.y-b.y; return guo; }
//	void outit() {printf("%f %f
",(float)x,(float)y); }
};
struct dian{
	int x,y;
	void mk(int cn, int cm) {x = cn; y = cm; }
	inline friend bool operator <(dian a, dian b) {return a.x == b.x ? a.y < b.y : a.x < b.x; }
	inline friend dian operator +(dian a, dian b) {dian guo; guo.x = a.x+b.x; guo.y = a.y+b.y; return guo; }
	inline friend dian operator -(dian a, dian b) {dian guo; guo.x = a.x-b.x; guo.y = a.y-b.y; return guo; }
	void outit() {printf("%d %d
",x,y); }
};
struct xian{
	dian2 A, B;
};
dian a[MAXN*16+1];
int alen;
int n;
int zhan[MAXN*16+1];
int zlen1, zlen2;
double ansr;
int ansA, ansB, ansC;
dian mk(int cn, int cm) {dian guo; guo.mk(cn, cm); return guo; }
void zeng(int cn, int cm) {if(0<=cn && cn<=MAXAI && 0<=cm && cm<=MAXAI) a[++alen].mk(cn,cm); }
LL chaji(dian A, dian B, dian C)
{
	LL dx1 = B.x-A.x, dx2 = C.x-A.x;
	LL dy1 = B.y-A.y, dy2 = C.y-A.y;
	return dx1*dy2-dx2*dy1;
}
dian2 zh(dian A, dian B) {dian2 guo; guo.x = (A.x+B.x)/2.0; guo.y = (A.y+B.y)/2.0; return guo; }
dian2 zhuan(dian A) {dian2 guo; guo.x = -A.y; guo.y = A.x; return guo; }
dian2 jiao(xian L1, xian L2)
{
	double kB = (L1.A.x*L1.B.y - L1.B.x*L1.A.y + L2.A.y*L1.B.x - L2.A.x*L1.B.y)/(L2.B.x*L1.B.y - L2.B.y*L1.B.x);
	dian2 guo; guo.x = L2.A.x + kB*L2.B.x; guo.y = L2.A.y + kB*L2.B.y;
	return guo;
}
dian2 suan_O(dian A, dian B, dian C)
{
//	printf("in suan_O :
");
//	A.outit(); B.outit(); C.outit();
	xian L1, L2;
	L1.A = zh(A, B); L1.B = zhuan(A-B); 
	L2.A = zh(B, C); L2.B = zhuan(B-C);
	dian2 guo = jiao(L1, L2);
//	guo.outit();
	return guo;
}
double suan_jlf(dian2 A, dian B) {return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); }
int pan(dian2 A, double R)
{
	if(zlen2 >= 4000) return 1;
	for(int i = 1;i<=zlen2;i++) if(suan_jlf(A, a[zhan[i]]) - R >= eps) return 0;
	return 1;
}
void jian(int cn, int cm, int cx)
{
	if(chaji(a[cn], a[cm], a[cx]) == 0) return;
	dian2 linO = suan_O(a[cn], a[cm], a[cx]);
	double linr = suan_jlf(linO, a[cn]);
	if(linr <= ansr) return;
	if(pan(linO, linr)) ansr = linr, ansA = cn, ansB = cm, ansC = cx;
}
int main()
{
//	freopen("emi.in","r",stdin);
//	freopen("emi.out","w",stdout);
//	suan_O(mk(0,0), mk(1,2), mk(2,1));
	Read(n); alen = 0;
	for(int i = 1;i<=n;i++) 
	{
		int bx,by,bz; Read(bx); Read(by); Read(bz);
		zeng(bx-bz, by); zeng(bx+bz, by);
		zeng(bx, by-bz); zeng(bx, by+bz);
		
		if(bx+by <= bz) zeng(0, 0);
		if(bx+MAXAI-by <= bz) zeng(0, MAXAI);
		if(MAXAI-bx+by <= bz) zeng(MAXAI, 0);
		if(MAXAI-bx+MAXAI-by <= bz) zeng(MAXAI, MAXAI);
		
		if(bx < bz) zeng(0, by-(bz-bx)), zeng(0, by+(bz-bx));
		if(by < bz) zeng(bx-(bz-by), 0), zeng(bx+(bz-by), 0);
		if(MAXAI-bx < bz) zeng(MAXAI, by+(bz+bx-MAXAI)), zeng(MAXAI, by-(bz+bx-MAXAI));
		if(MAXAI-by < bz) zeng(bx+(bz+by-MAXAI), MAXAI), zeng(bx-(bz+by-MAXAI), MAXAI);
	}
	sort(a+1, a+alen+1);
	zlen1 = 2; zhan[1] = 1; zhan[2] = 2;
	for(int i = 3;i<=alen;i++)
	{
		while(zlen1 >= 2 && chaji(a[zhan[zlen1-1]], a[zhan[zlen1]], a[i]) <= 0) zlen1--;
		zhan[++zlen1] = i;
	}
	zlen2 = zlen1+1; zhan[zlen2] = alen-1;
	for(int i = alen-2;i>=1;i--)
	{
		while(zlen2-zlen1 >= 1 && chaji(a[zhan[zlen2-1]], a[zhan[zlen2]], a[i]) <= 0) zlen2--;
		zhan[++zlen2] = i;
	}
	ansr = 0;
	jian(zhan[zlen2-1], zhan[1], zhan[2]);
	for(int i = 1;i<=zlen2-2;i++) jian(zhan[i], zhan[i+1], zhan[i+2]);
	a[ansA].outit(); a[ansB].outit(); a[ansC].outit();
	return 0;
}
原文地址:https://www.cnblogs.com/czyarl/p/13067256.html