题意:
给你一个光源 和n个圆形障碍物,现在光源向y = 0投影 问你被圆遮住的阴影区段有哪些?
思路:
图是偷的qaq 可以求出图中∠a和∠b 投影到下面幕布的区段: (b-a的正负不打紧,我们根据角度求映射距离,负角就变成了O.x+……了)
double OA = dis(O,a[i]);//圆心与光源的距离
double a = asin(a[i].r/OA);//R对角的角度
double b = asin((O.x-a[i].x)/OA);//圆心与y轴的角度
ans[i].L = O.x - O.y * tan(a+b);
ans[i].R = O.x - O.y * tan(b-a);
上代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
const int MaxN = 5e2 + 5;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
int n;
struct Circle{
double x,y,r;
Circle(double x = 0,double y = 0,double r = 0) : x(x),y(y),r(r) {}
}a[MaxN],O;
struct Seg{//投影阴影区段
double L,R;
}ans[MaxN];
bool cmp(Seg A,Seg B){
return A.L < B.L;
}
double dis(Circle A,Circle B){
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
int main()
{
int cnt = 0;
while(~scanf("%d",&n) && n){
scanf("%lf%lf",&O.x,&O.y);
for(int i = 1;i <= n; i++){
scanf("%lf %lf %lf",&a[i].x,&a[i].y,&a[i].r);
double OA = dis(O,a[i]);//圆心与光源的距离
double aa = asin(a[i].r/OA);//R对角的角度
double bb = asin((O.x-a[i].x)/OA);//圆心与y轴的角度
double angle1 = aa + bb;
double angle2 = bb - aa;
ans[i].L = O.x - O.y * tan(angle1);
ans[i].R = O.x - O.y * tan(angle2);
}
sort(ans + 1,ans + 1 + n,cmp);
double beg = ans[1].L;
double lst = ans[1].R;
if(cnt) printf("\n");
cnt++;
for(int i = 2;i <= n; i++){
if(ans[i].L > lst){
printf("%.2f %.2f\n",beg,lst);
beg = ans[i].L;
lst = ans[i].R;
}
else lst = max(lst,ans[i].R);//或者sort再加一行
}
printf("%.2f %.2f\n",beg,lst);
}
return 0;
}