[Algorithm Brushing Problem Solution Notes] POJ 1106 Transmitters [Computational Geometry|Cross Product|Point-Line Relationship]

topic link

Topic to the effect

  • Input the first line to give the center coordinates and radius of a circle, and then give n points. It is required to take out a semicircle in this circle, so that the semicircle covers the most points, and output the maximum number of points.

example input

  • The first line: the coordinates of the center of the circle and the radius of the circle
  • The second line: the number of points n
  • n lines after the second line: the coordinates of each point
  • There are several sets of input test data, the end mark of the input test data, input the coordinates of the center of a circle, and the radius is a negative number
25 25 3.5
7
25 28
23 27
27 27
24 23
26 23
24 29
26 29
350 200 2.0
5
350 202
350 199
350 198
348 200
352 200
995 995 10.0
4
1000 1000
999 998
990 992
1000 999
100 100 -2.5

sample output

3
4
4

problem solving ideas

  • For n points of each set of test data, it is only necessary to keep the points within the circle, because the points not within the circle cannot be within the semicircle, and invalid points are excluded to avoid invalid judgments
  • Since it is impossible for us to enumerate all the angles of the semicircle, because all the angles of the semicircle are infinitely many, that is, there are infinitely many ways to place the semicircle, so we should consider which ways to place the semicircle are useful.
  • In fact, we only need to enumerate the cases where the diameter of the semicircle coincides with any point in the circle, that is, to enumerate all possible cases where any point in the circle is on the diameter of the semicircle, the placement of the semicircle, because the optimal The semicircle must be just stuck on a point, so that enough space can be left for other points, so that the number of points in the semicircle is the largest .
    • image.png
  • So we only need to violently enumerate the boundary (any point in the circle is on the diameter), and then use the cross product to count the number of points in the semicircle under this placement, and finally take the maximum value from all possible cases. Can
    • When calculating, the diameter vector takes the representation of the center of the circle pointing to the point on the diameter inside the circle, and the semicircle is on the left side of the diameter
    • image.png
    • Therefore, the cross product with the radius vector is greater than or equal to 0 (counterclockwise), in the semicircle; otherwise not in the semicircle (clockwise)

problem solving code

#include <iostream>
using namespace std;

int main() {
    
    
	// 圆心和半径 
	double circle_x, circle_y, r;
	// 还有测试数据就继续 
	while (cin >> circle_x >> circle_y >> r) {
    
    
		if (r < 0) break; // 半径为负数,退出
		int n = 0; // 点的个数 
		cin >> n;
		// 存储在圆内的点 
        // 不知道为什么数组大小写n,动态创建数组,在POJ会报编译异常
		// double xi[n];
		// double yi[n];
        // 所以数组大小直接用字面量了
        double xi[100000];
        double yi[100000];
		int cnt = 0;
		for (int i=0; i<n; i++) {
    
    
			// 输入的每个点的坐标 
			double x, y;
			cin >> x >> y;
			// 只保存在圆内的点 
			if ( ((x - circle_x) * (x - circle_x) + (y - circle_y) * (y - circle_y)) <= r * r ) {
    
    
				xi[cnt] = x;
				yi[cnt] = y;
				cnt++;
			}
		}
		// 保存答案
		int ans = 0; // 在半圆内的点的最大个数 
		// 以在圆内的每个点为边界进行判断
		// 即直径在当前枚举的点的位置上 
		for (int i=0; i<cnt; i++) {
    
    
			double x = xi[i];
			double y = yi[i];
			// 直径向量
			double diameter_x = x - circle_x;
			double diameter_y = y - circle_y; 
			// 记录当前情况下的最大值
			int max_now = 0; 
			// 判断每个点是否在当前枚举的半圆内 
			for (int j=0; j<cnt; j++) {
    
    
				// 当前要判断是否在半圆内的点和圆心组成的向量 
				double vector_x = xi[j] - circle_x;
				double vector_y = yi[j] - circle_y; 
				// 通过叉积判断是否在半圆内 
				if ((vector_x * diameter_y) - (vector_y * diameter_x) >= 0) {
    
    
					max_now++;
				} 
			} 
			// 和另外半边圆的个数比较,取较大值 
			max_now = max_now > (cnt - max_now) ? max_now : (cnt - max_now);
            // 更新答案
			ans = ans < max_now ? max_now : ans;
		}
		cout << ans << endl; 
	}
} 
  • I don’t know why the uppercase and lowercase n of the array is created dynamically, and a compilation exception will be reported in POJ, so the size of the array is directly measured in literals.
  • image.png
  • image.png

Guess you like

Origin blog.csdn.net/m0_53022813/article/details/131111541