吉林大学OJ第2775题 Problem F: Shadows
吉林大学OJ第2775题,Problem F: Shadows(题目链接)。
Problem F: Shadows
“No sunshine but bath some shadow”. A shadow is an area where direct light from a light source cannot reach due to obstruction by an object. It occupies all of the space behind an opaque object with light in front of it.
Let us consider a simplified 2-D problems. There is a lamp at the origin and an unlimited wall on the straight line x=d. Some opaque objects float between them. All these objects are circle. The wall will be separated into light and shadow. The shadow of each circle may be overlapping no matter the circles are intersected or not.
Your task is to count the length of all shadows.
Input
The first line of each case are d and n. The real number d is the distance between wall and lamp, and integer n(0 < n < 100) is the number of circles. n=0 means the end of input.
The next n lines consist of three real number x, y and r. x and y are the coordinates of circle center. r is the radius of circle opaque object. The entire area of each circle is between the two straight lines x=0 and x=d.
Output
For each case, print the total length of all shadows, rounded to two digits after decimal point.
Sample Input
10.0 2
5 0 2
3 1 2
10 0
Sample Output
20.16
解题思路:用三角函数,算出各个圆的经过原点的切线的斜率。从而算出影子的上下界。然后按照上界排序。外离和外切,影子总长加上影子长度,更新当前下界;相交的,影子总长加上影子下界减去最新下界,更新当前下界,内切和内含的,忽略不计。最终输出影子总长。
C++语言源代码如下:
#include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; typedef int COUNT; typedef struct { double top, bottom; } Circle; bool cmp(const Circle & a, const Circle & b ) { if ( a.top > b.top ) return true; else return false ; } int main (void) { COUNT i, n; double distance; double x, y, r; double sum; double angle, angle_diff, top_angle, bottom_angle; Circle circle[105]; double bottom; while ( scanf( "%lf%d", &distance, &n ) , n ) { for ( i = 0 ; i < n ; i ++ ) { scanf( "%lf%lf%lf", &x, &y, &r ); angle = atan( y / x ); angle_diff = asin( r / sqrt(x*x + y*y) ); top_angle = angle + angle_diff; bottom_angle = angle - angle_diff; circle[i].top = distance * tan(top_angle); circle[i].bottom = distance * tan(bottom_angle ); } sort(circle, circle + n, cmp ); bottom = circle[0].bottom; sum = circle[0].top - circle[0].bottom; for ( i = 1 ; i < n ; i ++ ) { if ( circle[i].top <= bottom ) { sum += circle[i].top - circle[i].bottom ; bottom = circle[i].bottom; } else { if (circle[i].bottom < bottom ) { sum += bottom - circle[i].bottom ; bottom = circle[i].bottom ; } } } printf( "%.2lf\n", sum ); } return EXIT_SUCCESS; }