Problem:
最古の遺跡

問題

昔, そこには集落があり, 多くの人が暮らしていた. 人々は形も大きさも様々な建物を建てた. だが, それらの建造物は既に失われ, 文献と, 遺跡から見つかった柱だけが建造物の位置を知る手がかりだった.

文献には神殿の記述がある. 神殿は上から見ると正確に正方形になっており, その四隅には柱があった. 神殿がどの向きを向いていたかはわからない. また, 辺上や内部に柱があったかどうかもわからない. 考古学者たちは, 遺跡から見つかった柱の中で, 正方形になっているもののうち, 面積が最大のものが神殿に違いないと考えた.

柱の位置の座標が与えられるので, 4 本の柱でできる正方形のうち面積が最大のものを探し, その面積を出力するプログラムを書け. なお, 正方形の辺は座標軸に平行とは限らないことに注意せよ.

例

下の図の例では, 10 本の柱があり, 座標 (4, 2), (5, 2), (5, 3), (4, 3) にある 4 本と座標 (1, 1), (4, 0), (5, 3), (2, 4) にある 4 本が正方形をなしている. 面積が最大の正方形は後者で, その面積は 10 である.

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．入力はゼロ１つを含む行で終了する．

1 行目には, 遺跡から見つかった柱の本数 n が書かれている.

2 行目から n + 1 行目までの n 行の各々には, 柱の x 座標と y 座標が空白区切りで書かれている.

1 本の柱が 2 度以上現れることはない.

n は 1 ≤ n ≤ 3000 を満たす整数であり, 柱の x 座標と y 座標は 0 以上 5000 以下の整数である.

採点用データのうち, 配点の 30% 分は 1 ≤ n ≤ 100 を満たし, 配点の 60% 分は1 ≤ n ≤ 500 を満たす.

データセットの数は 10 を超えない．

出力

データセットごとに 1 個の整数を出力する. 4 本の柱からなる正方形が存在する場合は, そのような正方形のうち面積が最大のものの面積を出力し, そのような正方形が存在しない場合は 0 を出力せよ.

入出力例

入力例

10
9 4
4 3
1 1
4 2
2 4
5 8
4 0
5 3
0 5
5 2
10
9 4
4 3
1 1
4 2
2 4
5 8
4 0
5 3
0 5
5 2
0

出力例

10
10

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C++ (judge verdict: Accepted)

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>

#define mp       make_pair
#define pb       push_back
#define all(x)   (x).begin(),(x).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define repi(i,a,b) for(int i = (a); i < (b); i++)

using namespace std;

typedef    long long          ll;
typedef    unsigned long long ull;
typedef    vector<bool>       vb;
typedef    vector<int>        vi;
typedef    vector<vb>         vvb;
typedef    vector<vi>         vvi;
typedef    pair<int,int>      pii;

const int INF=1<<29;
const double EPS=1e-9;

const int dx[]={1,0,-1,0},dy[]={0,-1,0,1};
pii point[3010];
bool ex[5010][5010];
int main(){
	int n;
	while(cin>>n,n){
		if(n==0)break;
		rep(i,5010){
			rep(j,5010){
				ex[i][j]=false;

			}
		}
		memset(point, 0, sizeof(point));
		for(int i=0;i < n;i++){
			cin>>point[i].first>>point[i].second;
			ex[point[i].second][point[i].first]=true;
		}
		sort(point,point+n);
		/*rep(i,n){
			printf("(x,y) =(%d,%d)\n",point[i].first,point[i].second);
		}*/
			int ans =0;
			for(int i=0;i < n;i++){
				for(int j=0;j < n;j++){
					if(i==j)continue;
					int dx =abs(point[j].first-point[i].first);
					int dy =abs(point[j].second-point[i].second);
					int tmp =dx*dx+dy*dy;
					if(tmp<=ans)continue;
				/*printf("(x1,y1) =(%d,%d)\n",point[i].first,point[i].second);
				printf("(x2,y2) =(%d,%d)\n",point[j].first,point[j].second);
				printf("(dx,dy) = (%d,%d)\n",dx,dy);*/
				int nx1 =point[j].first+dy;
				int ny1 =point[j].second+dx;

				int nx2 =point[i].first+dy;
				int ny2 =point[i].second+dx;
				//
				int mnx1 =(point[j].first-dy);
				int mny1 =(point[j].second-dx);

				int mnx2 =(point[i].first-dy);
				int mny2 =(point[i].second-dx);
				/*printf("(nx1,ny1) =(%d,%d)\n",nx1,ny1);
				printf("(nx2,ny2) =(%d,%d)\n",nx2,ny2);
				printf("(mnx1,mny2) =(%d,%d)\n",mnx1,mny1);
				printf("(mnx1,mny2) =(%d,%d)\n",mnx2,mny2);
				cout <<endl;*/
				if(nx1<=5000&&ny1<=5000&&nx2<=5000&&ny2<=5000&&
				   ex[ny1][nx1]&&ex[ny2][nx2]){
					ans=max(ans,tmp);
				//cout <<ans<<endl;
				continue;
			}
			if(mnx1>=0&&mny1>=0&&mnx2>=0&&mny2>=0&&
			   ex[mny1][mnx1]&&ex[mny2][mnx2]){
				ans=max(ans,tmp);
		}
	}
}
cout <<ans<<endl;
}
return 0;
}