mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
dd3af96771
4900-4999
185 lines
5.4 KiB
C++
185 lines
5.4 KiB
C++
#include <iostream>
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <vector>
|
|
#define next (i+1)%n
|
|
const double eps = 1e-8;
|
|
using namespace std;
|
|
const double PI = acos(-1);
|
|
const double sqrt3 = sqrt(3);
|
|
int dcmp(double x)
|
|
{
|
|
if (x < -eps) return -1;
|
|
else if (x > eps) return 1;
|
|
else return 0;
|
|
}
|
|
double add(double a, double b)
|
|
{
|
|
if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
|
|
return a + b;
|
|
}
|
|
struct Point
|
|
{
|
|
double x,y;
|
|
Point() {}
|
|
Point(double x,double y) : x(x),y(y){}
|
|
Point operator + (Point p) {return Point(add(x, p.x),add(y, p.y)); }
|
|
Point operator - (Point p) {return Point(add(x, -p.x),add(y, -p.y)); }
|
|
Point operator * (double a) {return Point(x * a, y * a); }
|
|
Point operator / (double a) {return Point(x / a, y / a); }
|
|
bool operator < (const Point p) const {return dcmp(x - p.x) < 0 || dcmp(x - p.x) == 0 && dcmp(y - p.y)<0; }
|
|
bool operator == (const Point p) const {return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0; }
|
|
double dot(Point p) {return add(x * p.x, y * p.y); }
|
|
double det(Point p) {return add(x * p.y, -y * p.x); }
|
|
double length() {return sqrt(x*x + y*y); }
|
|
double Angle() {return atan2(y,x);}
|
|
Point Rotate(double rad) {return Point(add(x * cos(rad),- y * sin(rad)), add(x * sin(rad), y * cos(rad))); }
|
|
Point Normal() {return Point(-y / length(), x / length()); }
|
|
};
|
|
typedef Point Vector;
|
|
int ConvexHull(Point* p,int n, Point* ch)
|
|
{
|
|
sort(p,p+n);
|
|
int m = 0;
|
|
for (int i = 0; i < n ; i ++)
|
|
{
|
|
while (m > 1 && (ch[m-1] - ch[m-2]).det(p[i] - ch[m-2]) <= 0) m --;
|
|
ch[m++] = p[i];
|
|
}
|
|
int k = m;
|
|
for (int i = n-2; i >= 0; i--)
|
|
{
|
|
while (m > k &&(ch[m-1] - ch[m-2]).det(p[i] - ch[m-2]) <= 0) m--;
|
|
ch[m++] = p[i];
|
|
}
|
|
if (n > 1) m--;
|
|
return m;
|
|
}
|
|
struct Circle
|
|
{
|
|
Point c;
|
|
double r;
|
|
Circle(){}
|
|
Circle(Point c, double r): c(c),r(r){}
|
|
Point point(double a)
|
|
{
|
|
return Point(c.x + cos(a)*r, c.y + sin(a)*r);
|
|
}
|
|
}C;
|
|
int getLineCircleIntersection(Point p,Vector v,Circle C,Point sol[])
|
|
{
|
|
double t1,t2;
|
|
double a= v.x, b = p.x - C.c.x, c = v.y, d = p.y - C.c.y;
|
|
double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d -C.r*C.r;
|
|
double delta = f*f - 4*e*g;
|
|
if (dcmp(delta) < 0) return 0;
|
|
if (dcmp(delta) == 0)
|
|
{
|
|
t1 = t2 = -f / (2 * e); sol[0] = sol[1] = p + v*t1;
|
|
return 1;
|
|
}
|
|
t1 = (-f - sqrt(delta)) / (2*e); sol[0] = p + v*t1;
|
|
t2 = (-f + sqrt(delta)) / (2*e); sol[1] = p + v*t2;
|
|
return 2;
|
|
}
|
|
double getAngle(double R, double l)
|
|
{
|
|
return asin(R * sin( PI/6 ) / l) - PI/6;
|
|
}
|
|
bool OnSegment(Point p, Point a1, Point a2)
|
|
{
|
|
return dcmp((a1 - p).det(a2 - p)) == 0 && dcmp((a1 - p).dot(a2 - p)) < 0;
|
|
}
|
|
int cnt;
|
|
vector <pair<double,int> > ans;
|
|
bool Section(Point a,Point b,double R)
|
|
{
|
|
double aa = a.Angle(), bb = b.Angle();
|
|
double da = getAngle(R, a.length()), db = getAngle(R, b.length());
|
|
if (dcmp(aa-bb-PI) > 0) aa-=2*PI;
|
|
else if(dcmp(bb-aa-PI) > 0) bb-=2*PI;
|
|
double l=max(aa-da,bb-db), r = min(aa+da,bb+db);
|
|
if (dcmp(r-l)<0)
|
|
return false;
|
|
cnt++;
|
|
for(int i=0;i<6;i++)
|
|
{
|
|
l+=PI/3,r+=PI/3;
|
|
if(dcmp(l-PI)>=0) l -= 2*PI;
|
|
if(dcmp(r-PI)>=0) r -= 2*PI;
|
|
ans.push_back(make_pair(l,-1));
|
|
ans.push_back(make_pair(r,1) );
|
|
if(r < l) cnt--;
|
|
}
|
|
return true;
|
|
}
|
|
bool getSection(Point a, Point b, Circle C)
|
|
{
|
|
double lena = a.length(),lenb = b.length();
|
|
if (dcmp(lena-C.r) <= 0 && dcmp(lenb-C.r) <= 0)
|
|
return true;
|
|
Point sol[2];
|
|
int n = getLineCircleIntersection(a,b-a,C,sol);
|
|
double R = C.r*sqrt3;
|
|
if (dcmp(lena-C.r) > 0 && dcmp(lenb - C.r) > 0)
|
|
{
|
|
if (n == 0) return Section(a,b,R);
|
|
bool judge0 = OnSegment(sol[0],a,b);
|
|
bool judge1 = OnSegment(sol[1],a,b);
|
|
if (judge0 || judge1)
|
|
return Section(a,sol[0],R) && Section(sol[1],b,R);
|
|
return Section(a, b, R);
|
|
}
|
|
if (dcmp(lena - C.r) > 0)
|
|
return Section(a,sol[0],R);
|
|
return Section(sol[1],b,R);
|
|
}
|
|
Point P[2000],Hull[2000];
|
|
int main()
|
|
{
|
|
int T;
|
|
scanf("%d",&T);
|
|
for (int kase = 1; kase <= T; kase ++)
|
|
{
|
|
int m,r;
|
|
Circle C = Circle(Point(0,0),0);
|
|
scanf("%d%lf", &m, &C.r);
|
|
const double R = C.r*sqrt3;
|
|
bool flag = true;
|
|
for (int i = 0; i < m; i++)
|
|
scanf("%lf%lf", &P[i].x, &P[i].y);
|
|
int n = ConvexHull(P, m, Hull);
|
|
ans.clear();
|
|
cnt = 0;
|
|
for (int i = 0; i < n && flag; i++)
|
|
{
|
|
if (dcmp(Hull[i].length()-R) > 0 || dcmp(Hull[next].length()-R) > 0)
|
|
{
|
|
flag = false;
|
|
break;
|
|
}
|
|
flag = getSection(Hull[i],Hull[next],C);
|
|
}
|
|
if (flag)
|
|
{
|
|
sort(ans.begin(), ans.end());
|
|
int now = 0,h = 0;
|
|
for (int i = 0; i < ans.size(); i++)
|
|
{
|
|
now -= ans[i].second;
|
|
if (h == cnt)
|
|
break;
|
|
h = max(h, now);
|
|
}
|
|
if (h!=cnt)
|
|
flag = false;
|
|
}
|
|
printf("Case #%d: ", kase);
|
|
if (flag) printf("Succeeded.\n");
|
|
else printf("Failed.\n");
|
|
}
|
|
}
|