E——The cake is a lie(最小圓覆蓋)
阿新 • • 發佈:2020-09-15
題目連結:https://nanti.jisuanke.com/t/A1993
恐怖如斯...這個還打算用普通幾何來做後來發現是真的傻了...
聯動題目:Circle and Points(http://poj.org/problem?id=1981)
想法是用poj的那道題目當板子,用這個半徑為r的能最多包含幾個點 然後二分答案即可。
板子部分如下:
struct point { double x,y; void read() { scanf("%lf%lf",&x,&y); } void print() { printf("%lf%lf\n",x,y); } double friend dis(const point &a,const point &b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y)); } } p[Mn + 5]; struct alpha { double v; bool flag; bool friend operator <(const alpha &a,const alpha &b) { return a.v < b.v; } } alp[Mn* Mn + 5]; int solve(int n,double R)//半徑為R的圓最多能覆蓋多少個點 { int MAX = 0; for(int i = 0; i < n; i++) { int t = 0; for(int j = 0; j < n; j++) { if(i == j) continue; double theta,phi,D; D = dis(p[i],p[j]); if(D > 2.0 * R) continue; theta = atan2(p[j].y - p[i].y,p[j].x - p[i].x); if(theta < 0) theta += 2 * pi; phi = acos(D / (2.0 * R)); alp[t].v = theta - phi + 2 * pi; alp[t].flag = true; alp[t + 1].v = theta + phi + 2 * pi; alp[t + 1].flag = false; t += 2; } sort(alp,alp + t); int sum = 0; for(int j = 0; j < t; j++) { if(alp[j].flag) sum ++; else sum --; if(sum > MAX) MAX = sum; } } return MAX+1; }
全部程式碼如下:
#include<bits/stdc++.h> #define Mn 300 #define sqr(x) ((x) * (x)) using namespace std; const double eps = 1e-9; const double pi = acos(-1.0); struct point { double x,y; void read() { scanf("%lf%lf",&x,&y); } void print() { printf("%lf%lf\n",x,y); } double friend dis(const point &a,const point &b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y)); } } p[Mn + 5]; struct alpha { double v; bool flag; bool friend operator <(const alpha &a,const alpha &b) { return a.v < b.v; } } alp[Mn * Mn + 5]; int solve(int n,double R) { int MAX = 0; for(int i = 0; i < n; i++) { int t = 0; for(int j = 0; j < n; j++) { if(i == j) continue; double theta,phi,D; D = dis(p[i],p[j]); if(D > 2.0 * R) continue; theta = atan2(p[j].y - p[i].y,p[j].x - p[i].x); if(theta < 0) theta += 2 * pi; phi = acos(D / (2.0 * R)); alp[t].v = theta - phi + 2 * pi; alp[t].flag = true; alp[t + 1].v = theta + phi + 2 * pi; alp[t + 1].flag = false; t += 2; } sort(alp,alp + t); int sum = 0; for(int j = 0; j < t; j++) { if(alp[j].flag) sum ++; else sum --; if(sum > MAX) MAX = sum; } } return MAX+1; } int main() { int t; scanf("%d",&t); double eps=1e-5; while(t--) { int n,s; scanf("%d %d",&n,&s); for (int i = 0; i < n; ++i) { scanf("%lf %lf",&p[i].x,&p[i].y); } int str_r; scanf("%d",&str_r); if(n<s) { printf("The cake is a lie.\n"); } else { double l=0,r=9999999; while(fabs(l-r)>eps) { double mid=(l+r)/2.0; int num=solve(n,mid); if (num>=s) { r=mid; } else { l=mid; } } printf("%.4f\n",l+str_r); } } }