Problem:
Convex-Cut

N個の頂点からなる凸多角形が与えられる。各頂点の座標は反時計周りに(X1, Y1), (X2 ,Y2), ……, (XN, YN)で表わされる。
点Pを通るどのような直線で凸多角形を切断しても、切断後に得られる2つの凸多角形の面積が等しいような点Pの座標を求めよ。

Input

入力は以下の形式で与えられる。

N
X1 Y1
X2 Y2
……
XN YN

Constraints

入力は全て整数である

3 ≤ N ≤ 50

0 ≤ |Xi|, |Yi| ≤ 1000000

入力の多角形は単純な凸多角形である。

出力は、出力座標を(X, Y)、厳密解を(cX, cY)とした時にmax(|X-cX|, |Y-cY|) ≤ 0.0001を満たす必要がある

Output

問題文の条件を満たす点があるのならば、その点の座標を

X Y

の形式で出力せよ。
点が存在しない場合は"NA"と1行に出力せよ。

Sample Input 1

4
100 100
0 100
0 0
100 0

以下の図に対応する。

Output for the Sample Input 1

50.00000 50.00000

Sample Input 2

3
100 100
0 100
0 0

Output for the Sample Input 2

NA

以下の図に対応する。

Solution in JAVA (judge verdict: Wrong Answer)


import java.awt.geom.*;
import java.util.*;
import static java.lang.Math.*;

public class Main {
	final Scanner sc=new Scanner(System.in);
	public static void main(String[] args) {
		new Main().init();
	}
	void init(){
		new B();
	}
	
	class B{
		B(){
			while(sc.hasNext()){
				int n = sc.nextInt();
				Point2D [] plist = new Point2D[n];
				for(int i = 0 ; i < n; i++){
					plist[i] = new Point2D.Double(sc.nextInt(), sc.nextInt());
				}
				if(n % 2 != 0){
					System.out.println("NA");
					continue;
				}
				ArrayList<Line2D> llist = new ArrayList<Line2D>();
				for(int i = 0 ; i < n / 2; i++){
					llist.add(new Line2D.Double(plist[i], plist[i + (n / 2)]));
				}
				
				boolean flg = true;
				Point2D ans = null;
				for(int i = 0 ; i < llist.size(); i++){
					for(int j = i + 1; j < llist.size(); j++){
						Point2D now = intersect(llist.get(i), llist.get(j));
						if(ans == null){
							ans = now;
							continue;
						}
						if(ans.distance(now) > EPS){
							flg = false;
							break;
							
						}
					}
					if(! flg ){
						break;
					}
				}
				//debug
//				for(int i = 0 ; i < llist.size(); i++){
//					System.out.println(llist.get(i).getP1() + " " + llist.get(i).getP2() );
//				}
				if(n == 4){
					Point2D p1 = sub(plist[0], plist[1]);
					Point2D p2 = sub(plist[0], plist[3]);
					Point2D p3 = sub(plist[2], plist[1]);
					Point2D p4 = sub(plist[3], plist[2]);
					if(Math.abs(dot(p1, p2)) < EPS && Math.abs(dot(p3,p4)) < EPS){
						System.out.printf("%f %f\n", ans.getX() , ans.getY());
					}
				}
				else if(ans != null && flg){
					//System.out.println(ans);
					System.out.printf("%f %f\n", ans.getX() , ans.getY());
				}
				else{
					System.out.println("NA");
				}
			}
			
		}
		private double dot(Point2D p1, Point2D p2) {
			double res = p1.getX() * p2.getX() + p1.getY() * p2.getY();
			return res;
		}
		double EPS = 1.0e-04;

		private boolean issame(Point2D p1, Point2D p2) {
			if(Math.abs(p1.getX() - p2.getX()) < EPS && Math.abs(p1.getY() - p2.getY()) < EPS){
				return true;
			}
			return false;
		}

		private Point2D intersect(Line2D l, Line2D m) {
			Point2D lv = sub(l.getP2(), l.getP1());
			Point2D mv = sub(m.getP2(), m.getP1());
			Point2D mlv = sub(m.getP1(), l.getP1());
			double a = cross(mlv, lv);
			double b = cross(lv, mv);
			if(Math.abs(a) < EPS && Math.abs(b) < EPS){
				return l.getP1();
			}
			double t = a / b;
			double resx = m.getX1() + t * mv.getX();
			double resy = m.getY1() + t * mv.getY();
			
			return new Point2D.Double(resx, resy);
		}

		private double cross(Point2D p1, Point2D p2) {
			double res = p1.getX() * p2.getY() - p1.getY() * p2.getX();
			return res;
		}

		private Point2D sub(Point2D p2, Point2D p1) {
			double x = p2.getX() - p1.getX();
			double y = p2.getY() - p1.getY();
			
			return new Point2D.Double(x,y);
		}
	}
	
	class C{
		C(){
			int M=sc.nextInt();
			HashMap<String, Num> map=new HashMap<String, Num>();
			for(int i=0; i<M; i++){
				String str=sc.next();
				int a=sc.nextInt(),b=sc.nextInt();
				map.put(str, new Num(a, b, (a==0||b==0)));
			}
			int N=sc.nextInt();
			String[] e=new String[N];
			for(int i=0; i<N; i++)	e[i]=sc.next();
			
			// TODO debug
			//System.out.println(Arrays.toString(e));
			
			boolean er=false;
			LinkedList<Num> s=new LinkedList<Num>();
			for(int i=0; i<N; i++){
				// TODO debug
				//System.out.println(s);
				
				if(map.containsKey(e[i])){
					s.push(map.get(e[i]));
				}else{
					try{
						int tmp=Integer.parseInt(e[i]);
						s.push(new Num(tmp,tmp,tmp==0));
					}catch(Exception ex){
						Num b=s.pop(),a=s.pop();
						if(e[i].equals("+")){
							boolean z=(a.hi+b.hi)>255;
							s.push(new Num(min(255,(a.lo+b.lo)), min(255,(a.hi+b.hi)), z));
						}else if(e[i].equals("-")){
							boolean z=(a.lo-b.hi)<=0;
							s.push(new Num(max(0, (a.lo-b.hi)), max(0, (a.hi-b.lo)), z));
						}else if(e[i].equals("*")){
							boolean z=a.zero||b.zero;
							int max=0;
							for(int aa=a.lo; aa<=a.hi; aa++){
								for(int bb=b.lo; bb<=b.hi; bb++){
									if(aa*bb>=256){
										z|=(aa*bb==256);
										break;
									}
									max=max(max,aa*bb);
								}
								if(max==255 && z)	break;
							}
							s.push(new Num(min(max, a.lo*b.lo), max, z));
						}
						else if(e[i].equals("/")){
							if(b.zero){
								// TODO debug
								//System.out.println("ER"+i);
								er=true;
								break;
							}
							int max=0,min=255;
							boolean z=a.zero;
							for(int aa=a.lo; aa<=a.hi; aa++){
								for(int bb=b.lo; bb<=b.hi; bb++){
									max=max(max, aa/bb);
									min=min(min, aa/bb);
									z|=(aa/bb==0);
									if(aa/bb<=0)	break;
								}
							}
							s.push(new Num(min, max, z));
						}
					}
				}
			}
			System.out.println(er?"error":"correct");
		}
		class Num{
			int lo,hi;
			boolean c,zero;
			Num(int lo,int hi,boolean zero){
				this.lo=lo;
				this.hi=hi;
				this.zero=zero || lo==0 || hi==0;
			}
			@Override public String toString(){
				return "(LO"+lo+" HI"+hi+" z-"+zero+")";
			}
		}
	}
	
	
}