您的位置:首页 > 其它

UVA 11177 凸多边形和圆交

2015-10-02 15:46 225 查看
#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 二分半径求重合面积
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: