/*
 * Copyright (c) 2004 Kamo Hiroyasu
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Circle and Points
 *  Author: Kamo Hiroyasu <wd@ics.nara-wu.ac.jp>
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef M_SQRT1_2
#define SQRT1_2	M_SQRT1_2
#else
#define SQRT1_2	0.70710678118654752440
#endif

struct point {
	double		x, y;
};

struct area {
	struct point	center;
	double		radius;
	int		count;
};

struct heap {
	int		max_count;
	struct area	*array;
	size_t		capacity, used;
};

int	count_points(const struct point *, int, double);
int	fgetpoints(struct point **, FILE *);

#define getpoints(p)	fgetpoints((p), stdin)

static int
is_on_disk(const struct point *p, const struct point *c, double rr)
{
	double		x, y;

	x = p->x - c->x;
	y = p->y - c->y;
	return x * x + y * y <= rr;
}

void
heap_initialize(struct heap *h)
{
	h->max_count = 0;
	h->capacity = 512;
	h->array = malloc(sizeof(struct area) * h->capacity);
	h->used = 0;
}

void
heap_terminate(struct heap *h)
{
	free(h->array);
}

void
heap_insert(struct heap *h, double x, double y, double a,
	    const struct point *p, int n, double r)
{
	double		rr, rra;
	struct point	c;
	int		k, k1;
	int		i;
	size_t		s, t;

	rr = r * r;
	rra = (r + a) * (r + a);
	c.x = x;
	c.y = y;
	k = k1 = 0;
	for (i = 0; i < n; i ++) {
		if (is_on_disk(&p[i], &c, rra)) {
			k1 ++;
			if (is_on_disk(&p[i], &c, rr)) {
				k ++;
			}
		}
	}
	if (k1 > h->max_count) {
		if (h->used > h->capacity) {
			struct area	*ptr;

			h->capacity *= 2;
			ptr = realloc(h->array,
				      sizeof(struct area) * h->capacity);
			if (ptr == NULL) {
				perror(NULL);
				exit(1);
			}
			h->array = ptr;
		}
		if (k > h->max_count) {
			h->max_count = k;
		}
		s = h->used;
		while (s > 0 && h->array[t = (s - 1) / 2].count < k) {
			h->array[s] = h->array[t];
			s = t;
		}
		h->array[s].count = k;
		h->array[s].center = c;
		h->array[s].radius = a;
		h->used ++;
	}
}

void
heap_remove_top(struct heap *h)
{
	size_t		s, t, t1, u;

	u = -- h->used;
	s = 0;
	while ((t = s * 2 + 1) <= u) {
		if ((t1 = t + 1) <= u &&
		    h->array[t].count < h->array[t1].count) {
			t = t1;
		}
		if (h->array[t].count < h->array[u].count) {
			break;
		}
		h->array[s] = h->array[t];
		s = t;
	}
	h->array[s] = h->array[u];
}

static void
count_points_base(const struct point *p, int n, double r, struct heap *h)
{
	double		x_min, x_max, y_min, y_max;
	double		x, y;
	double		x_diff, y_diff;
	int		i;

	x_min = x_max = p[0].x;
	y_min = y_max = p[0].y;
	for (i = 1; i < n; i ++) {
		x = p[i].x;
		if (x < x_min) {
			x_min = x;
		} else if (x > x_max) {
			x_max = x;
		}
		y = p[i].y;
		if (y < y_min) {
			y_min = y;
		} else if (y > y_max) {
			y_max = y;
		}
	}
	x_diff = x_max - x_min;
	y_diff = y_max - y_min;
	heap_insert(h, (x_min + x_max) / 2, (y_min + y_max) / 2,
		    (x_diff >= y_diff ? x_diff : y_diff) * SQRT1_2,
		    p, n, r);
}

static void
count_points_step(const struct point *p, int n, double r, struct heap *h)
{
	double		x0, y0;
	double		a0, a, d;

	x0 = h->array[0].center.x;
	y0 = h->array[0].center.y;
	a0 = h->array[0].radius;
	heap_remove_top(h);
	a = a0 * 0.5;
	d = a * SQRT1_2;
	heap_insert(h, x0 + d, y0 + d, a, p, n, r);
	heap_insert(h, x0 - d, y0 + d, a, p, n, r);
	heap_insert(h, x0 + d, y0 - d, a, p, n, r);
	heap_insert(h, x0 - d, y0 - d, a, p, n, r);
}

int
count_points(const struct point *p, int n, double r)
{
	struct heap	heap;
	int		count;

	heap_initialize(&heap);
	count_points_base(p, n, r, &heap);
	while (heap.used > 0) {
		count_points_step(p, n, r, &heap);
	}
	count = heap.max_count;
	heap_terminate(&heap);
	return count;
}

int
fgetpoints(struct point **pp, FILE *fp)
{
	int		i, n;
	struct point	*p;

	if (fscanf(fp, "%d", &n) != 1 || n < 0) {
		return -1;
	}
	p = malloc(n * sizeof(struct point));
	if (p == NULL) {
		return -1;
	}
	for (i = 0; i < n; i ++) {
		if (fscanf(fp, "%lf%lf", &p[i].x, &p[i].y) != 2) {
			free(p);
			return -1;
		}
	}
	*pp = p;
	return n;
}

main()
{
	int		n;
	struct point	*p;

	while ((n = getpoints(&p)) > 0) {
		printf("%d\n", count_points(p, n, 1.0));
		free(p);
	}
	return n == 0 ? 0 : 1;
}
