回复 12楼 九转星河
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#define MAX_POINTS (100) ///<
/**
*\brief 点
*/
typedef struct point_st{
double x;
double y;
}point_st;
/**
*\brief 线
*/
typedef struct line_st{
unsigned int is_ek; ///< 斜率存在否 0不存在 1存在
double k; ///< 斜率 y = kx + b
double b; ///< 如果斜率不存在 表示 x的坐标
}line_st;
/**
*\brief 集合
*/
typedef struct set_st{
unsigned int idx_list[MAX_POINTS]; ///< 点的下标值
unsigned int count; ///< 集合的规模
line_st line; ///< 第一、二圆的公共弦 所在的直线
}set_st;
static unsigned int s_points_num; ///< 输入的点数量
static double s_r; ///< 半径长度
static point_st s_points[MAX_POINTS]; ///< 点列表
static unsigned int s_sets_num;
static set_st s_sets[MAX_POINTS*MAX_POINTS]; ///< 点集
/**
*\brief 捕获终端输入
*/
static int get_input(void)
{
unsigned int i = 0;
scanf("%u %lf", &s_points_num, &s_r);
assert(MAX_POINTS >= s_points_num);
for (i = 0; i < s_points_num; ++i){
scanf("%lf %lf", &s_points[i].x, &s_points[i].y);
}
return 0;
}
/**
*\brief 求两点间的距离
*/
static inline double get_dis(unsigned int i, unsigned int j)
{
double x, y;
x = pow(s_points[i].x - s_points[j].x, 2.0);
y = pow(s_points[i].y - s_points[j].y, 2.0);
return sqrt(x + y);
}
/**
*\brief 获取两直线的交点
*/
static int get_collision_point(line_st *l_1, line_st *l_2, point_st *point)
{
if (l_1->is_ek == 0 && l_2->is_ek == 1){
point->x = l_1->b;
point->y = l_2->k * point->x + l_2->b;
return 1;
}else if (l_1->is_ek == 1 && l_2->is_ek == 0){
point->x = l_2->b;
point->y = l_1->k * point->x + l_1->b;
return 1;
}else if (l_1->is_ek == 1 && l_2->is_ek == 1){
point->x = (l_1->b - l_2->b)/(l_2->k - l_1->k);
point->y = l_1->k * point->x + l_1->b;
return 1;
}
return 0;
}
/**
*\brief 求最大覆盖
*/
static int get_max_cover(void)
{
unsigned int i = 0, j = 0, k = 0, max = 0;
s_sets_num = 0;
for (i = 0; i < s_points_num; ++i){
for (j = i + 1; j < s_points_num; ++j){
if (2 * s_r < get_dis(i, j)){
continue;
}
s_sets[s_sets_num].idx_list[0] = i;
s_sets[s_sets_num].idx_list[1] = j;
s_sets[s_sets_num].count = 2;
if (s_points[i].y == s_points[j].y){// 斜率不存在
s_sets[s_sets_num].line.is_ek = 0; // x = (pi.x + pi.x)/2
s_sets[s_sets_num].line.b = (s_points[j].x + s_points[i].x)/2.0;
}else{
s_sets[s_sets_num].line.is_ek = 1;
s_sets[s_sets_num].line.k = (s_points[j].x - s_points[i].x)/(s_points[i].y - s_points[j].y);
s_sets[s_sets_num].line.b = (pow(s_points[i].x,2.0) + pow(s_points[i].y,2.0) - pow(s_points[j].x, 2.0) - pow(s_points[j].y, 2.0))/(2*(s_points[i].y - s_points[j].y));
}
++s_sets_num;
}
}
for (i = 0; i < s_points_num; ++i){// 遍历所有的点
for (j = 0; j < s_sets_num; ++j){// 遍历所有的集合
for (k = 0; k < s_sets[j].count; ++k){// 遍历集合中的点
if (s_sets[j].idx_list[k] == i){
break; // 同一个点
}
if (2 * s_r < get_dis(i, s_sets[j].idx_list[k])){
break;
}
}
if (k >= s_sets[j].count){
// 取集合中第一个点与该点相交 会获得一个直线
unsigned int idx; ///< 斜率存在否 0不存在 1存在
line_st line;
point_st point;
idx = s_sets[j].idx_list[0];
if (s_points[idx].y == s_points[i].y){// 斜率不存在
line.is_ek = 0; // x = (pi.x + pi.x)/2
line.b = (s_points[idx].x + s_points[i].x)/2.0;
}else{
line.is_ek = 1;
line.k = (s_points[idx].x - s_points[i].x)/(s_points[i].y - s_points[idx].y);
line.b = (pow(s_points[i].x,2.0) + pow(s_points[i].y,2.0) - pow(s_points[idx].x, 2.0) - pow(s_points[idx].y, 2.0))/(2*(s_points[i].y - s_points[idx].y));
}
// 求2直线的交点
get_collision_point(&s_sets[j].line, &line, &point);
for (k = 0; k < s_sets[j].count; ++k){// 遍历集合中的点
idx = s_sets[j].idx_list[k];
if (pow(point.x - s_points[idx].x,2.0) + pow(point.y - s_points[idx].y,2.0) > 1){
break;
}
}
if (k >= s_sets[j].count){
s_sets[j].idx_list[s_sets[j].count] = i;
++s_sets[j].count;
}
}
}
}
for (i = 0; i < s_sets_num; ++i){
if (max < s_sets[i].count){
max = s_sets[i].count;
}
}
printf("\tres[%u]\n", max);
return 0;
}
int main(void)
{
get_input();
get_max_cover();
return 0;
}