<>
<>
题目大意:
给一个光源点s,给一些圆,源点和s相切会形成阴影,求每一段阴影在横轴上的区间。
解题分析:
这道其实不需要点与圆切线的板子来求解,完全可以根据角度和线段长度之间的关系计算。
解此题的方法就是,先单独对每一个圆研究,算出它们各自在横轴上的投影区间,然后,再求出这些区间的并,把每一段区间输出即可。
当然,我们应该要注意到,点与圆的位置关系不只有这一种情况,还一种情况是,圆的圆形没有超过垂线,但是圆的圆心X+R超过了垂线,但是,经过简单证明发现,其实这两种情况都可以用一个表达式来表示,所以下面的代码只用写一种形式。
#include#include #include #include using namespace std;#define MAXN 503struct Ln //投影的区间{ double l, r;//区间的左右端点横坐标 bool operator<(const Ln &b)const { return l < b.l; }}lns[MAXN];int N; //水管总数int main(){ while (~scanf("%d", &N) && N) { int Lx, Ly; //light 灯的坐标 scanf("%d%d", &Lx, &Ly); for (int p = 0; p < N; p++) { int Ox, Oy, r; scanf("%d%d%d", &Ox, &Oy, &r);//input double OL = sqrt(double(Ox - Lx)*(Ox - Lx) + (Oy - Ly)*(Oy - Ly)); double alpha = asin((Lx - Ox) / OL);//∠OLC double beta = asin(r / OL);//∠OLA lns[p].l = Lx - Ly * tan(alpha + beta); lns[p].r = Lx - Ly * tan(alpha - beta); } sort(lns, lns + N); double L = lns[0].l, R = lns[0].r;//初始化第一个区间 for (int p = 1; p < N; p++) { if (lns[p].l > R) { printf("%.2lf %.2lf\n", L, R);//output//输出上一个 L = lns[p].l, R = lns[p].r;//初始化下一个 } else R = max(lns[p].r, R); //由于会出现长区间包含短区间的情况 因而需要比较大小 } printf("%.2lf %.2lf\n\n", L, R); //output//输出最后一个大区间,这里不要忘记 } return 0;}
2018-08-01