/* C re-implementation of meastman-1.py * * Author: Matt Eastman <matt@meastman.org> */ #include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct { double x; double y; } Point; const double kEpsilon = 0.00001; Point* set_point(Point* point, double x, double y) { point->x = x; point->y = y; return point; } /* Find up to 2 circles of radius r that touch a and b. */ Point** find_circles(Point* a, Point* b, double r) { /* See http://stackoverflow.com/questions/3349125/circle-circle-intersection-points */ static Point out0, out1; static Point* out[3]; double ab_dist = sqrt(pow(a->x - b->x, 2) + pow(a->y - b->y, 2)); if ((ab_dist > r * 2 + kEpsilon) || (ab_dist == 0)) { out[0] = NULL; return out; } double h = sqrt(pow(r, 2) - pow(ab_dist, 2) / 4); double mid_x = (a->x + b->x) / 2; double mid_y = (a->y + b->y) / 2; double x_rhs = h * (b->y - a->y) / ab_dist; double y_rhs = h * (b->x - a->x) / ab_dist; out[0] = set_point(&out0, mid_x + x_rhs, mid_y - y_rhs); out[1] = set_point(&out1, mid_x - x_rhs, mid_y + y_rhs); out[2] = NULL; return out; } /* Determine which points are within a given circle. */ int points_in_circle(Point* center, double r, Point** points) { int count = 0; double r2 = pow(r, 2) + kEpsilon; int i; for (i = 0; points[i] != NULL; i++) { if (pow(points[i]->x - center->x, 2) + pow(points[i]->y - center->y, 2) <= r2) count++; } return count; } void read_case(double* radiusOut, Point*** pointsOut) { static Point* points = NULL; static Point** pPoints = NULL; static int pointsAlloc = -1; int numZombies, i; scanf("%lf %d", radiusOut, &numZombies); if (numZombies > pointsAlloc) { pointsAlloc = numZombies; points = (Point*)realloc(points, sizeof(Point)*numZombies); pPoints = (Point**)realloc(pPoints, sizeof(Point*)*(numZombies + 1)); } for (i = 0; i < numZombies; i++) { scanf("%lf %lf", &points[i].x, &points[i].y); pPoints[i] = &points[i]; } pPoints[numZombies] = NULL; *pointsOut = pPoints; } void solve_case(double radius, Point** points) { int maxHitCount = 0, hitCount, i, j, k; Point** centers; /* Try each zombie as a hit target. * Necessary if no 2 zombies are within 2*r of each other. */ for (i = 0; points[i] != NULL; i++) { hitCount = points_in_circle(points[i], radius, points); if (hitCount > maxHitCount) maxHitCount = hitCount; } /* For each pair of zombies, there can be up to 2 circles of radius r that * touch both points/zombies. * Try the center of each of these as a hit target. */ for (i = 0; points[i] != NULL; i++) { for (j = i + 1; points[j] != NULL; j++) { centers = find_circles(points[i], points[j], radius); for (k = 0; centers[k] != NULL; k++) { hitCount = points_in_circle(centers[k], radius, points); if (hitCount > maxHitCount) maxHitCount = hitCount; } } } printf("%d\n", maxHitCount); } int main() { int numCases, i; Point** points; double radius; scanf("%d", &numCases); for (i = 0; i < numCases; i++) { read_case(&radius, &points); solve_case(radius, points); } return 0; }