UVA 11177 凸多边形和圆交

#define _USE_MATH_DEFINES
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
struct Vertex
{
	double x, y;
};
int vc;
Vertex vs[64];
double dis[64];
enum ItType { N, IO, OI };
struct IVtx
{
	Vertex v;
	ItType t;
};
bool inside(double x)
{
	const double eps = 1e-8;
	return 0 - eps < x && x < 1 + eps;
}
int GetIt(Vertex &va, Vertex &vb, double r, double &t0, double &t1)
{
	const double eps = 1e-8;
	double A = (vb.x - va.x)*(vb.x - va.x) + (vb.y - va.y)*(vb.y - va.y);
	double B = 2 * (va.x*(vb.x - va.x) + va.y*(vb.y - va.y));
	double C = va.x*va.x + va.y*va.y - r * r;
	double delta = B * B - 4 * A * C;
	if (delta < -eps)
		return 0;
	else if (delta < eps)
	{
		t0 = -B / (2 * A);
		return inside(t0) ? 1 : 0;
	}
	else
	{
		double sd = sqrt(delta);
		t0 = (-B - sd) / (2 * A);
		int rc = 0;
		if (inside(t0))
		{
			rc++;
			t1 = (-B + sd) / (2 * A);
			if (inside(t1))
				rc++;
		}
		else
		{
			t0 = (-B + sd) / (2 * A);
			if (inside(t0))
				rc++;
		}
		return rc;
	}
}
void GetArea(vector<IVtx> &ia, double r)
{
	for (int i = 0; i < vc; i++)
	{
		IVtx it;
		Vertex k;
		Vertex &va = vs[i], &vb = vs[(i + 1) % vc];
		double t0, t1;
		if (dis[i] >= r * r || dis[(i + 1) % vc] >= r * r)
		{
			switch (GetIt(va, vb, r, t0, t1))
			{
			case 0: break; // no It
			case 1:
				k.x = va.x + (vb.x - va.x) * t0;
				k.y = va.y + (vb.y - va.y) * t0;
				it.v = k;
				if (dis[i] <= r * r && dis[(i + 1) % vc] >= r * r)
				{
					it.t = IO;
					ia.push_back(it);
				}
				else if (dis[i] >= r * r && dis[(i + 1) % vc] <= r * r)
				{
					it.t = OI;
					ia.push_back(it);
				}
				else
					;// pass
				break;
			case 2:
				k.x = va.x + (vb.x - va.x) * t0;
				k.y = va.y + (vb.y - va.y) * t0;
				it.v = k;
				it.t = OI;
				ia.push_back(it);
				k.x = va.x + (vb.x - va.x) * t1;
				k.y = va.y + (vb.y - va.y) * t1;
				it.v = k;
				it.t = IO;
				ia.push_back(it);
				break;
			}
		}
		else
		{
			it.t = N;
			it.v = va;
			ia.push_back(it);
			it.v = vb;
			ia.push_back(it);
		}
	}
}
double TriArea(Vertex a, Vertex b/*, Vertex c*/)
{
	//return (a.x - c.x)*(b.y - c.y) - (a.y - c.y)*(b.x - c.x);
	//c(0,0)
	return a.x * b.y - a.y * b.x;
}
double CalcArea(double r)
{
	vector<IVtx> its;
	GetArea(its, r);
	if (its.empty())
		return M_PI * r * r;
	else
	{
		double ans = 0;
		int c = its.size();
		for (int i = 0; i < c; i++)
		{
			if (its[i].t == IO && its[(i + 1) % c].t == OI)
			{
				double t0 = atan2(its[i].v.y, its[i].v.x);
				double t1 = atan2(its[(i + 1) % c].v.y, its[(i + 1) % c].v.x);
				double p = max(t0, t1) - min(t0, t1);
				p = min(p, M_PI * 2 - p);
				ans += p / 2 * r * r;
			}
			else
				ans += abs(TriArea(its[i].v, its[(i + 1) % c].v) / 2);
		}
		return ans;
	}
}
int main()
{
	int tc = 1;
	while (scanf("%d", &vc) != EOF && vc)
	{
		double area;
		scanf("%lf", &area);
		double maxdis = 0;
		for (int i = 0; i < vc; i++)
		{
			scanf("%lf%lf", &vs[i].x, &vs[i].y);
			dis[i] = vs[i].x * vs[i].x + vs[i].y * vs[i].y;
			maxdis = max(maxdis, dis[i]);
		}
		const double eps = 1e-3;
		double l = 0, r = maxdis;
		while (abs(r - l) > eps)
		{
			double m = (r + l) / 2;
			double a = CalcArea(m);
			if (a > area)
				r = m;
			else
				l = m;
		}
		printf("Case %d: %.2lf\n", tc++, (l + r) / 2);
	}
	return 0;
}

UVA 11177 二分半径求重合面积


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值