Problem:
Score : 300 points

Problem Statement

There are N balls in a two-dimensional plane. The i-th ball is at coordinates (x_i, y_i).

We will collect all of these balls, by choosing two integers p and q such that p \neq 0 or q \neq 0 and then repeating the following operation:

Choose a ball remaining in the plane and collect it. Let (a, b) be the coordinates of this ball. If we collected a ball at coordinates (a - p, b - q) in the previous operation, the cost of this operation is 0. Otherwise, including when this is the first time to do this operation, the cost of this operation is 1.

Find the minimum total cost required to collect all the balls when we optimally choose p and q.

Constraints

1 \leq N \leq 50

|x_i|, |y_i| \leq 10^9

If i \neq j, x_i \neq x_j or y_i \neq y_j.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the minimum total cost required to collect all the balls.

Sample Input 1

2
1 1
2 2

Sample Output 1

1

If we choose p = 1, q = 1, we can collect all the balls at a cost of 1 by collecting them in the order (1, 1), (2, 2).

Sample Input 2

3
1 4
4 6
7 8

Sample Output 2

1

If we choose p = -3, q = -2, we can collect all the balls at a cost of 1 by collecting them in the order (7, 8), (4, 6), (1, 4).

Sample Input 3

4
1 1
1 2
2 1
2 2

Sample Output 3

2

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_BALL_MAX		50										// 最大ボール数
#define D_PTN_MAX		D_BALL_MAX * D_BALL_MAX / 2				// 最大パターン数

// 内部構造体 - 値情報
typedef struct Val {
	int miX, miY;
} Val;

// 内部変数
static FILE *szpFpI;											// 入力
static Val sz1Ball[D_BALL_MAX];									// ボール
static int siBCnt;												// ボール数
static Val sz1Ptn[D_PTN_MAX];									// パターン
static int siPCnt;												// パターン数

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpA;
	static int siTNo;
#endif

// 出力
int
fOut(
	char *pcpLine				// <I> １行
)
{
	char lc1Buf[1024];

#ifdef D_TEST
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, pcpLine)) {
		siRes = -1;
	}
#else
	printf("%s", pcpLine);
#endif

	return 0;
}

// ソート関数 - X昇順 - Y昇順
int
fSortFnc(
	const void *pzpVal1			// <I> 値１
	, const void *pzpVal2		// <I> 値２
)
{
	Val *lzpVal1 = (Val *)pzpVal1;
	Val *lzpVal2 = (Val *)pzpVal2;

	// X昇順
	if (lzpVal1->miX > lzpVal2->miX) {
		return 1;
	}
	else if (lzpVal1->miX < lzpVal2->miX) {
		return -1;
	}

	// Y昇順
	if (lzpVal1->miY > lzpVal2->miY) {
		return 1;
	}
	else if (lzpVal1->miY < lzpVal2->miY) {
		return -1;
	}

	return 0;
}

// 最大値 - 取得
int
fGetMax(
	int piVal1					// <I> 値１
	, int piVal2				// <I> 値２
)
{
	if (piVal1 > piVal2) {
		return piVal1;
	}
	else {
		return piVal2;
	}
}

// 実行メイン
int
fMain(
)
{
	int i, j;
	char lc1Buf[1024];

	// ボール数 - 取得
	fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
	sscanf(lc1Buf, "%d", &siBCnt);
	if (siBCnt <= 2) {
		return 1;
	}

	// ボール - 取得
	for (i = 0; i < siBCnt; i++) {
		fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
		sscanf(lc1Buf, "%d%d", &sz1Ball[i].miX, &sz1Ball[i].miY);
	}

	// ボール - ソート
	qsort(sz1Ball, siBCnt, sizeof(Val), fSortFnc);

	// パターン - セット
	for (i = 0; i < siBCnt - 1; i++) {
		for (j = i + 1; j < siBCnt; j++) {
			sz1Ptn[siPCnt].miX = sz1Ball[j].miX - sz1Ball[i].miX;
			sz1Ptn[siPCnt].miY = sz1Ball[j].miY - sz1Ball[i].miY;
			siPCnt++;
		}
	}

	// パターン - ソート
	qsort(sz1Ptn, siPCnt, sizeof(Val), fSortFnc);

	// 最大パターン数 - 取得
	int liX = sz1Ptn[0].miX;
	int liY = sz1Ptn[0].miY;
	int liCnt = 1;
	int liMax = liCnt;
	for (i = 1; i < siPCnt; i++) {
		if (sz1Ptn[i].miX == liX && sz1Ptn[i].miY == liY) {
			liCnt++;
			liMax = fGetMax(liMax, liCnt);
		}
		else {
			liX = sz1Ptn[i].miX;
			liY = sz1Ptn[i].miY;
			liCnt = 1;
		}
	}

	return siBCnt - liMax;
}

// １回実行
int
fOne(
)
{
	int liRet;
	char lc1Buf[1024];

	// 入力 - セット
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", siTNo);
	szpFpI = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", siTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#else
	szpFpI = stdin;
#endif

	// 実行メイン
	liRet = fMain();

	// 出力
	sprintf(lc1Buf, "%d\n", liRet);
	fOut(lc1Buf);

	// 残データ有無
#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, "")) {
		siRes = -1;
	}
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpI);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", siTNo);
	}
	else {
		printf("NG %d\n", siTNo);
	}
#endif

	return 0;
}

// プログラム開始
int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		siTNo = i;
		fOne();
	}
#else
	fOne();
#endif

	return 0;
}