Codeforces 135 B. Rectangle and Square
問題
8つの点が与えられる。
それらを4つの点からなる共通しない集合2つに分ける。
そのうち一方が正方形の4頂点になっていて、もう一方が長方形の4頂点になっている(正方形でもよい)ような分け方は存在するか。
存在するならYESおよびその分け方を一通り出力し、そうでないならNOを出力せよ。
面積が0の図形は長方形または正方形とはみなさないものとする。
制約条件
座標の絶対値は10^4以下
方針
集合の分け方を全通り、集合のどの点がABCDのどの点に対応するかを全通り試す。
正方形、長方形の判定は、
- ABベクトルがDCベクトルに等しい
- ABベクトルを90度回転させるとADベクトルと平行になる
- 正方形の場合、ABベクトルを90度回転させるとADベクトルに一致する
により行えばよい。
ソースコード
typedef complex<double> P; vi X,Y; bool ck(vi a,bool square){ do{ P p[4]; rep(i,4)p[i]=P(X[a[i]],Y[a[i]]); rep(i,4)rep(j,i)if(abs(p[i]-p[j])<EPS)return 0; if(abs(p[1]-p[0]-(p[2]-p[3]))>EPS)continue; if(abs((p[1]-p[0])/abs(p[1]-p[0])-(p[3]-p[0])/abs(p[3]-p[0])*P(0,1))>EPS)continue; if(square&&abs(abs(p[1]-p[0])-abs(p[3]-p[0]))>EPS)continue; return 1; }while(next_permutation(all(a))); return 0; } void run() { X.clear(); Y.clear(); int x,y; rep(i,8){ cin>>x>>y; X.pb(x); Y.pb(y); } rep(i,1<<8){ vi a,b; rep(j,8)if(i&1<<j)a.pb(j); else b.pb(j); if(a.size()!=4)continue; if(ck(a,1)&&ck(b,0)){ cout<<"YES"<<endl; rep(j,4)cout<<a[j]+1<<(j==3?"\n":" "); rep(j,4)cout<<b[j]+1<<(j==3?"\n":" "); goto END; } } cout<<"NO"<<endl; END:; }