Problem:
Problem I:
Light The Room
You are given plans of rooms of polygonal shapes. The walls of the rooms on the plans are
placed parallel to either
x
-axis or
y
-axis. In addition, the walls are made of special materials so
they reflect light from sources as mirrors do, but only once. In other words, the walls do not
reflect light already reflected at another point of the walls.
Now we have each room furnished with one lamp. Walls will be illuminated by the lamp directly
or indirectly. However, since the walls reflect the light only once, some part of the walls may
not be illuminated.
You are requested to write a program that calculates the total length of
unilluminated
part of
the walls.
Figure 10: The room given as the second case in Sample Input
Input
The input consists of multiple test cases.
The first line of each case contains a single positive even integer
N
(4 ≤
N
≤ 20), which indicates
the number of the corners. The following
N
lines describe the corners counterclockwise. The
i-th line contains two integers
x
i
and
y
i
, where (
x
i
,
y
i
) indicates the coordinates of the
i
-th
corner. The last line of the case contains
x'
and
y'
, where (
x'
,
y'
) indicates the coordinates of
the lamp.
To make the problem simple, you may assume that the input meets the following conditions:
All coordinate values are integers not greater than 100 in their absolute values.
No two walls intersect or touch except for their ends.
The walls do not intersect nor touch each other.
The walls turn each corner by a right angle.
The lamp exists strictly inside the room off the wall.
The x-coordinate of the lamp does not coincide with that of any wall; neither does the
     y-coordinate.
The input is terminated by a line containing a single zero.
Output
For each case, output the length of the unilluminated part in one line. The output value may
have an arbitrary number of decimal digits, but may not contain an error greater than 10
-3
.
Sample Input
4
0 0
2 0
2 2
0 2
1 1
6
2 2
2 5
0 5
0 0
5 0
5 2
1 4
0
Output for the Sample Input
0.000
3.000

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-6;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectLS(const L& l, const L& s){
    return cross(l[1]-l[0], s[0]-l[0])*
        cross(l[1]-l[0], s[1]-l[0]) < EPS;
}
bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) < 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) < 0 );
}

P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
P reflection(const L& l, const P& p) {
    return p + 2.0*(projection(l, p) -p);
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        VP p(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            p[i] = P(x, y);
        }
        int sx,sy;
        cin >> sx >> sy;
        P source(sx, sy);

        vector<L> edge(n);
        vector<VP> cp(n);
        for(int i=0; i<n; i++){
            edge[i] = L(p[i], p[(i+1)%n]);
            cp[i].push_back(edge[i][0]);
            cp[i].push_back(edge[i][1]);
        }

        for(int v=0; v<n; v++){
            L ray(source, p[v]);
            for(int wr=0; wr<n; wr++){
                if(!isParallel(ray, edge[wr]) && intersectLS(ray, edge[wr])){
                    P cpll = crosspointLL(ray, edge[wr]);
                    //直接頂点を通る
                    cp[wr].push_back(cpll);
                    //その後反射する
                    P ref = reflection(edge[wr], source);
                    L ray2(ref, cpll);
                    for(int wt=0; wt<n; wt++){
                        if(!isParallel(ray2, edge[wt]) && intersectLS(ray2, edge[wt])){
                            cp[wt].push_back(crosspointLL(ray2, edge[wt]));
                        }
                    }
                }
            }

            //反射して頂点を通る
            for(int wr=0; wr<n; wr++){
                P s = reflection(edge[wr], source);
                L ray(s, p[v]);
                for(int wt=0; wt<n; wt++){
                    if(!isParallel(ray, edge[wt]) && intersectLS(ray, edge[wt])){
                        cp[wt].push_back(crosspointLL(ray, edge[wt]));
                    }
                }
            }
        }
        for(int i=0; i<n; i++){
            sort(cp[i].begin(), cp[i].end());
            cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
        }

        double ans = 0;
        for(int i=0; i<n; i++){
            for(int j=0; j<(int)cp[i].size()-1; j++){
                P mid = (cp[i][j] +cp[i][j+1]) /2.0;
                bool light = false;
                //反射する壁を選ぶ
                for(int wr=0; wr<n; wr++){
                    P ref = reflection(edge[wr], mid);
                    if(!intersectSS(L(ref, source), edge[wr])) continue;
                    P rp;
                    if(isParallel(L(ref, source), edge[wr])){
                        rp = (ref +source) /2.0;
                    }else{
                        rp = crosspointLL(L(ref, source), edge[wr]);
                    }
                    vector<L> ray{L(mid, rp), L(rp, source)};

                    bool block = false;
                    for(int k=0; k<2; k++){
                        for(int w=0; w<n; w++){
                            if(!isParallel(ray[k], edge[w]) && strictItsSS(ray[k], edge[w])){
                                block = true;
                                k = 2;
                                break;
                            }
                        }
                    }
                    if(!block){
                        light = true;
                        break;
                    }
                }
                if(!light){
                    ans += abs(cp[i][j+1] -cp[i][j]);
                }
            }
        }

        cout << fixed << setprecision(10);
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3332
final_rank: 3

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }
  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }
  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }
};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s)const { return (p1==s.p1) ? p2 < s.p2 : p1 < s.p1; } 
  bool operator == (const Segment& p)const { return ( p.p1 == p1 && p.p2 == p2 ) || ( p.p1 == p2 && p.p2 == p1 ); }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }
double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }
double norm(Point a){ return a.x*a.x+a.y*a.y; }
double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}

Point reflection(Line l,Point p) { return p + (projection(l, p) - p) * 2; }

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    return vec[1];
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}

double angle(Point a,Point b,Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux*vx + uy*vy)/sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)));
}  
  
//多角形poly内（線分上も含む）に点pが存在するかどうは判定する  
bool inPolygon(Polygon poly,Point p){
  if((int)poly.size() == 0)return false;
  rep(i,poly.size()) if(onSegment(poly[i],poly[(i+1)%poly.size()],p))return true;
  double sum = 0;
  for(int i=0; i < (int)poly.size() ;i++) {
    if( equals(cross(poly[i]-p,poly[(i+1)%poly.size()]-p),0.0) ) continue; // ３点が平行だとangleがnanを返しsumがnanになり死ぬ
    if( cross3p(p,poly[i],poly[(i+1)%poly.size()]) < 0 ) sum -= angle(p,poly[i],poly[(i+1)%poly.size()]);
    else                                                 sum += angle(p,poly[i],poly[(i+1)%poly.size()]);
  }
  // あまり誤差を厳しくしすぎると良くないので以下のほうが良い 
  const double eps = 1e-5;
  return (fabs(sum - 2*M_PI) < eps || fabs(sum + 2*M_PI) < eps);
}  

bool inPolygon(const Polygon &poly,Segment seg){
  vector<Point> vp;
  vp.push_back(seg.p1);
  vp.push_back(seg.p2);
  rep(i,(int)poly.size()) {
    Segment edge = Segment(poly[i],poly[(i+1)%(int)poly.size()]);
    if( equals(cross(seg.p1-seg.p2,edge.p1-edge.p2),0.0) ) {
      if( onSegment(seg.p1,seg.p2,edge.p1) ) vp.push_back(edge.p1);
      if( onSegment(seg.p1,seg.p2,edge.p2) ) vp.push_back(edge.p2);
    } else {
      if( intersectSS(seg,edge) ) vp.push_back(crosspoint(seg,edge));
    }
  }
  sort(vp.begin(),vp.end());
  vp.erase(unique(vp.begin(),vp.end()),vp.end());
  rep(i,(int)vp.size()-1) {
    Point middle_point = ( vp[i] + vp[i+1] ) / 2.0;
    if( !inPolygon(poly,middle_point) ) return false;
  }
  return true;  
}

int V;
Polygon poly;
Point light;

// type 0 => =w=, type 1 => mirror
void inner_add_new_points(Polygon &pol,vector<Point> &vp,int type,Line ref){
  rep(i,V){
    // ライトから普通のポリゴンの角をみる
    Vector e = ( poly[i] - light ) / abs( poly[i] - light );
    Segment seg = Segment(light,light+e*10000);
    rep(j,V) {
      Segment poly_seg = Segment(pol[j],pol[(j+1)%V]);
      if( equals(cross(seg.p2-seg.p1,poly_seg.p2-poly_seg.p1),0.0) ) continue;
      if( intersectSS(poly_seg,seg) ) {
        if( !type ) vp.push_back(crosspoint(poly_seg,seg));
        else        vp.push_back(reflection(ref,crosspoint(poly_seg,seg)));
      }
    }

    // ライトから反転したポリゴンの角をみる
    e = ( pol[i] - light ) / abs( pol[i] - light );
    seg = Segment(light,light+e*10000);
    rep(j,V) {
      Segment poly_seg = Segment(pol[j],pol[(j+1)%V]);
      if( equals(cross(seg.p2-seg.p1,poly_seg.p2-poly_seg.p1),0.0) ) continue;
      if( intersectSS(poly_seg,seg) ) {
        if( !type ) vp.push_back(crosspoint(poly_seg,seg));
        else        vp.push_back(reflection(ref,crosspoint(poly_seg,seg)));
      }
    }
  }
}

bool  LT(double a,double b) { return !equals(a,b) && a < b; } 
bool LTE(double a,double b) { return  equals(a,b) || a < b; } 

Point vir;
bool comp_dist(const Point& p1,const Point& p2){ return LT(abs(vir-p1),abs(vir-p2)); }

void add_new_points(Polygon &new_poly){
  vector<Point> vp;
  inner_add_new_points(poly,vp,0,Line());
  rep(i,V){
    Line ref = Line(poly[i],poly[(i+1)%V]);
    Polygon rpoly(V);
    rep(j,V) {
      rpoly[j] = reflection(ref,poly[j]);
      if( equals(rpoly[j].x,0.0) ) rpoly[j].x = 0;
      if( equals(rpoly[j].y,0.0) ) rpoly[j].y = 0;
    }
    inner_add_new_points(rpoly,vp,1,ref);
  }

  rep(i,(int)vp.size()) {
    if( equals(vp[i].x,0.0) ) vp[i].x = 0;
    if( equals(vp[i].y,0.0) ) vp[i].y = 0;
  }

  vector<Point> tmp;
  rep(i,vp.size()) {
    bool failed = false;
    rep(j,V) if( vp[i] == poly[j] ) { failed = true; break; }
    if( !failed ) tmp.push_back(vp[i]);
  }
  vp = tmp;

  sort(vp.begin(),vp.end());
  vp.erase(unique(vp.begin(),vp.end()),vp.end());

  rep(i,V){
    vector<Point> buf;
    Segment seg = Segment(poly[i],poly[(i+1)%V]);
    rep(j,(int)vp.size()) if( onSegment(seg.p1,seg.p2,vp[j]) ) buf.push_back(vp[j]);
    vir = seg.p1;
    sort(buf.begin(),buf.end(),comp_dist);
    rep(j,(int)buf.size()) new_poly.push_back(buf[j]);
    new_poly.push_back(seg.p2);
  }  
}

void compute_saw(Polygon &npoly,bool *saw){
  
  int nV = npoly.size();  
  // 直接見れる
  rep(i,nV) {
    Point mp = ( npoly[i] + npoly[(i+1)%nV] ) / 2.0;
    Segment vline = Segment(light,mp);
    bool failed = false;
    rep(j,V) {
      Segment seg = Segment(poly[j],poly[(j+1)%V]);
      if( equals(cross(seg.p1-seg.p2,vline.p1-vline.p2),0.0) ) continue;
      if( intersectSS(seg,vline) ) {
        if( onSegment(seg.p1,seg.p2,vline.p1) || onSegment(seg.p1,seg.p2,vline.p2) ) continue;
        if( onSegment(vline.p1,vline.p2,seg.p1) || onSegment(vline.p1,vline.p2,seg.p2) ) continue;
        failed = true;
        break;
      }
    }
    if( failed ) continue;
    saw[i] = true;
  }

  // 鏡一枚で見れる
  // 直接見える鏡だけを列挙
  vector<Line> ref;
  rep(i,nV) {
    Point mp = ( npoly[i] + npoly[(i+1)%nV] ) / 2.0;
    Segment vline = Segment(light,mp);
    bool failed = false;
    rep(j,V) {
      Segment seg = Segment(poly[j],poly[(j+1)%V]);
      if( equals(cross(seg.p1-seg.p2,vline.p1-vline.p2),0.0) ) continue;
      if( intersectSS(seg,vline) ) {
        if( onSegment(seg.p1,seg.p2,vline.p1) || onSegment(seg.p1,seg.p2,vline.p2) ) continue;
        if( onSegment(vline.p1,vline.p2,seg.p1) || onSegment(vline.p1,vline.p2,seg.p2) ) continue;
        failed = true;
        break;
      }
    }
    if( !failed ) ref.push_back(Line(npoly[i],npoly[(i+1)%nV]));
  }
  
  vector<Polygon> ref_polies;
  rep(i,(int)ref.size()){
    Polygon tmp_poly;
    rep(j,(int)poly.size()) tmp_poly.push_back(reflection(ref[i],poly[j]));
    ref_polies.push_back(tmp_poly);
  }

  rep(i,nV) if( !saw[i] ) {
    rep(j,(int)ref.size()){
      Segment rev_edge = Segment(reflection(ref[j],npoly[i]),reflection(ref[j],npoly[(i+1)%nV]));
      Point rev_mp = ( rev_edge.p1 + rev_edge.p2 ) / 2.0;
      Segment rev_vline = Segment(light,rev_mp);
      if( equals(cross(rev_vline.p1-rev_vline.p2,ref[j].p1-ref[j].p2),0.0) ) continue;
      if( !intersectSS(rev_vline,ref[j]) ) continue;
      rev_vline.p1 = crosspoint(rev_vline,ref[j]);
      if( inPolygon(ref_polies[j],rev_vline) ) {
        saw[i] = true;
        break;
      }
    }
  }
}

void compute(){
  Polygon npoly;
  add_new_points(npoly);
  int nV = npoly.size();
  bool saw[nV];
  rep(i,nV) saw[i] = false;
  compute_saw(npoly,saw);
  double sum = 0;
  rep(i,nV) if( !saw[i] )sum += abs(npoly[(i+1)%nV]-npoly[i]);
  sum = fabs(sum);
  printf("%.10lf\n",sum);
}

int main(){
  while( cin >> V, V ){
    poly.resize(V);
    rep(i,V) cin >> poly[i].x >> poly[i].y;
    cin >> light.x >> light.y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1540
final_rank: 4

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-6)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s)const { return (p1==s.p1) ? p2 < s.p2 : p1 < s.p1; } 
  bool operator == (const Segment& p)const { return ( p.p1 == p1 && p.p2 == p2 ) || ( p.p1 == p2 && p.p2 == p1 ); }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev から cur へ行って next へ行く際の角度を求める
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //同じセグメントかもよ
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}
  

bool isConvex(vector<Point> p) {
  int sz = (int)p.size();
  if(sz < 3)return false;//boundary case, we treat a point or a line as not convex
  bool isLeft = ccwtest(p[0],p[1],p[2]);
  for(int i=1; i<(int)p.size();i++)
    if(ccwtest(p[i],p[(i+1)%sz],p[(i+2)%sz]) != isLeft) return false;
  return true;
}


double angle(Point a,Point b,Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux*vx + uy*vy)/sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)));
}  
  
//多角形poly内（線分上も含む）に点pが存在するかどうは判定する  
bool inPolygon(Polygon poly,Point p){
  if((int)poly.size() == 0)return false;
  rep(i,poly.size()) if(onSegment(poly[i],poly[(i+1)%poly.size()],p))return true;
  double sum = 0;
  for(int i=0; i < (int)poly.size() ;i++) {
    if( equals(cross(poly[i]-p,poly[(i+1)%poly.size()]-p),0.0) ) continue; // ３点が平行だとangleがnanを返しsumがnanになり死ぬ
    if( cross3p(p,poly[i],poly[(i+1)%poly.size()]) < 0 ) sum -= angle(p,poly[i],poly[(i+1)%poly.size()]);
    else                                                 sum += angle(p,poly[i],poly[(i+1)%poly.size()]);
  }
  // あまり誤差を厳しくしすぎると良くないので以下のほうが良い 
  const double eps = 1e-5;
  return (fabs(sum - 2*M_PI) < eps || fabs(sum + 2*M_PI) < eps);
}  

bool inPolygon(const Polygon &poly,Segment seg){
  vector<Point> vp;
  vp.push_back(seg.p1);
  vp.push_back(seg.p2);
  rep(i,(int)poly.size()) {
    Segment edge = Segment(poly[i],poly[(i+1)%(int)poly.size()]);
    if( equals(cross(seg.p1-seg.p2,edge.p1-edge.p2),0.0) ) {
      if( onSegment(seg.p1,seg.p2,edge.p1) ) vp.push_back(edge.p1);
      if( onSegment(seg.p1,seg.p2,edge.p2) ) vp.push_back(edge.p2);
    } else {
      if( intersectSS(seg,edge) ) vp.push_back(crosspoint(seg,edge));
    }
  }
  sort(vp.begin(),vp.end());
  vp.erase(unique(vp.begin(),vp.end()),vp.end());
  rep(i,(int)vp.size()-1) {
    Point middle_point = ( vp[i] + vp[i+1] ) / 2.0;
    if( !inPolygon(poly,middle_point) ) return false;
  }
  return true;  
}

int V;
Polygon poly;
Point light;

// type 0 => =w=, type 1 => mirror
void inner_add_new_points(Polygon &pol,vector<Point> &vp,int type,Line ref){
  rep(i,V){
    Vector e = ( poly[i] - light ) / abs( poly[i] - light );
    Segment seg = Segment(light,light+e*10000);
    rep(j,V) {
      Segment poly_seg = Segment(pol[j],pol[(j+1)%V]);
      if( equals(cross(seg.p2-seg.p1,poly_seg.p2-poly_seg.p1),0.0) ) continue;
      if( intersectSS(poly_seg,seg) ) {
        if( !type ) vp.push_back(crosspoint(poly_seg,seg));
        else        vp.push_back(reflection(ref,crosspoint(poly_seg,seg)));
      }
    }

    e = ( pol[i] - light ) / abs( pol[i] - light );
    seg = Segment(light,light+e*10000);
    rep(j,V) {
      Segment poly_seg = Segment(pol[j],pol[(j+1)%V]);
      if( equals(cross(seg.p2-seg.p1,poly_seg.p2-poly_seg.p1),0.0) ) continue;
      if( intersectSS(poly_seg,seg) ) {
        if( !type ) vp.push_back(crosspoint(poly_seg,seg));
        else        vp.push_back(reflection(ref,crosspoint(poly_seg,seg)));
      }
    }

  }
}

bool  LT(double a,double b) { return !equals(a,b) && a < b; } 
bool LTE(double a,double b) { return  equals(a,b) || a < b; } 

Point vir;
bool comp_dist(const Point& p1,const Point& p2){ return LT(abs(vir-p1),abs(vir-p2)); }

void add_new_points(Polygon &new_poly){
  vector<Point> vp;

  inner_add_new_points(poly,vp,0,Line());
  rep(i,V){
    Line ref = Line(poly[i],poly[(i+1)%V]);
    Polygon rpoly(V);
    rep(j,V) {
      rpoly[j] = reflection(ref,poly[j]);
      if( equals(rpoly[j].x,0.0) ) rpoly[j].x = 0;
      if( equals(rpoly[j].y,0.0) ) rpoly[j].y = 0;
    }
    inner_add_new_points(rpoly,vp,1,ref);
  }


  /*
  // 直接見える点の列挙
  rep(i,V){
    Vector e = ( poly[i] - light ) / abs( poly[i] - light );
    Segment vline = Segment(light,light+e*10000);
    rep(j,V){
      Segment seg = Segment(poly[j],poly[(j+1)%V]);
      if( equals(cross(vline.p1-vline.p2,seg.p1-seg.p2),0.0) ) continue;
      if( intersectSS(vline,seg) ) {
        if( onSegment(vline.p1,vline.p2,seg.p1) || onSegment(vline.p1,vline.p2,seg.p2) ) continue;
        if( onSegment(seg.p1,seg.p2,vline.p1)   || onSegment(seg.p1,seg.p2,vline.p2)   ) continue;
        vp.push_back(crosspoint(vline,seg));
      }
    }
  }

  // 鏡に反射して見える点の列挙

  rep(i,V){
    Line ref = Line(poly[i],poly[(i+1)%V]);
    Polygon rev_poly;
    rep(j,V) rev_poly.push_back(reflection(ref,poly[j]));    
    

  }
  */


  //------------------------------

  rep(i,(int)vp.size()) {
    if( equals(vp[i].x,0.0) ) vp[i].x = 0;
    if( equals(vp[i].y,0.0) ) vp[i].y = 0;
  }

  vector<Point> tmp;
  rep(i,vp.size()) {
    bool failed = false;
    rep(j,V) if( vp[i] == poly[j] ) { failed = true; break; }
    if( !failed ) tmp.push_back(vp[i]);
  }
  vp = tmp;

  sort(vp.begin(),vp.end());
  vp.erase(unique(vp.begin(),vp.end()),vp.end());

  rep(i,V){
    vector<Point> buf;
    Segment seg = Segment(poly[i],poly[(i+1)%V]);
    rep(j,(int)vp.size()) if( onSegment(seg.p1,seg.p2,vp[j]) ) buf.push_back(vp[j]);
    vir = seg.p1;
    sort(buf.begin(),buf.end(),comp_dist);
    rep(j,(int)buf.size()) new_poly.push_back(buf[j]);
    new_poly.push_back(seg.p2);
  }  

}

void compute_saw(Polygon &npoly,bool *saw){
  
  int nV = npoly.size();  
  // 直接見れる

  rep(i,nV) {
    Point mp = ( npoly[i] + npoly[(i+1)%nV] ) / 2.0;
    Segment vline = Segment(light,mp);
    bool failed = false;
    rep(j,V) {
      Segment seg = Segment(poly[j],poly[(j+1)%V]);
      if( equals(cross(seg.p1-seg.p2,vline.p1-vline.p2),0.0) ) continue;
      if( intersectSS(seg,vline) ) {
        if( onSegment(seg.p1,seg.p2,vline.p1) || onSegment(seg.p1,seg.p2,vline.p2) ) continue;
        if( onSegment(vline.p1,vline.p2,seg.p1) || onSegment(vline.p1,vline.p2,seg.p2) ) continue;
        failed = true;
        break;
      }
    }
    if( failed ) continue;
    saw[i] = true;
  }
  /*
  cout << "direct see" << endl;
  rep(i,nV) if( saw[i] )cout << npoly[i] << "," << npoly[(i+1)%nV]<< endl;
  cout << endl;
  */
  // 鏡一枚で見れる

  // 直接見える鏡だけを列挙
  vector<Line> ref;
  rep(i,nV) {
    Point mp = ( npoly[i] + npoly[(i+1)%nV] ) / 2.0;
    Segment vline = Segment(light,mp);
    bool failed = false;
    rep(j,V) {
      Segment seg = Segment(poly[j],poly[(j+1)%V]);
      if( equals(cross(seg.p1-seg.p2,vline.p1-vline.p2),0.0) ) continue;
      if( intersectSS(seg,vline) ) {
        if( onSegment(seg.p1,seg.p2,vline.p1) || onSegment(seg.p1,seg.p2,vline.p2) ) continue;
        if( onSegment(vline.p1,vline.p2,seg.p1) || onSegment(vline.p1,vline.p2,seg.p2) ) continue;
        failed = true;
        break;
      }
    }
    if( !failed ) ref.push_back(Line(npoly[i],npoly[(i+1)%nV]));
  }
  
  vector<Polygon> ref_polies;
  rep(i,(int)ref.size()){
    Polygon tmp_poly;
    rep(j,(int)poly.size()) tmp_poly.push_back(reflection(ref[i],poly[j]));
    ref_polies.push_back(tmp_poly);
  }
  /*
  rep(i,(int)ref.size()) {
    cout << "ref[" << i << "] = " << ref[i] << endl;
    rep(j,(int)ref_polies[i].size()){
      cout << " " << ref_polies[i][j];
    } cout << endl;
  }
  */

  rep(i,nV) if( !saw[i] ) {
    rep(j,(int)ref.size()){
      Segment rev_edge = Segment(reflection(ref[j],npoly[i]),reflection(ref[j],npoly[(i+1)%nV]));
      Point rev_mp = ( rev_edge.p1 + rev_edge.p2 ) / 2.0;
      Segment rev_vline = Segment(light,rev_mp);
      if( equals(cross(rev_vline.p1-rev_vline.p2,ref[j].p1-ref[j].p2),0.0) ) continue;
      if( !intersectSS(rev_vline,ref[j]) ) continue;

      rev_vline.p1 = crosspoint(rev_vline,ref[j]);
      
      if( inPolygon(ref_polies[j],rev_vline) ) {
        saw[i] = true;
        break;
      }

    }
  }
  
}

void compute(){
  Polygon npoly;
  add_new_points(npoly);
  int nV = npoly.size();
  rep(i,nV) {
    if( equals(npoly[i].x,0.0) ) npoly[i].x = 0;
    if( equals(npoly[i].y,0.0) ) npoly[i].y = 0;
  }
  bool saw[nV];
  rep(i,nV) saw[i] = false;
  compute_saw(npoly,saw);
  rep(i,nV) {
    if( equals(npoly[i].x,0.0) ) npoly[i].x = 0;
    if( equals(npoly[i].y,0.0) ) npoly[i].y = 0;
  }
  /*
  cout << "nV = " << nV << endl;
  rep(i,nV) cout << i << "-th " << npoly[i] << endl;
  cout << endl;

  rep(i,nV) {
    if( !saw[i] ) cout << "cannot see " << npoly[i] << "," << npoly[(i+1)%nV] << " : " << abs(npoly[i]-npoly[(i+1)%nV]) << endl;
  }
  */

  double sum = 0;
  rep(i,nV) if( !saw[i] )sum += abs(npoly[(i+1)%nV]-npoly[i]);
  sum = fabs(sum);
  printf("%.10lf\n",sum);
}

int main(){
  while( cin >> V, V ){
    poly.resize(V);
    rep(i,V) cin >> poly[i].x >> poly[i].y;
    cin >> light.x >> light.y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 1548
final_rank: 5

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) {
  if (intersectSP(s,t[0]) || intersectSP(s,t[1]) ||
      intersectSP(t,s[0]) || intersectSP(t,s[1])) return 0;
  return intersectSS(s,t);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectLP(h,s[0]) || intersectLP(h,s[1]) ||
      intersectLP(s,h[0]) || intersectLP(s,h[1])) return 0;
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

int n;
L pl[20];
vector<P> v[20];


int mostNearest(const L &h) {
  double mi = INF;
  int res = -1;
  REP(k,n) {
    if (intersectHS(h,pl[k])) {
      if (chmin(mi,norm(crosspoint(h,pl[k])-h[0]))) {
        res = k;
      }
    }
  }
  return res;
}


void func(const L &h) {
  int cl_id = mostNearest(h);
  if (cl_id != -1) {
    v[cl_id].push_back(crosspoint(h,pl[cl_id]));
  }
}

P c;

bool isVisible(const P &p, const P &q) { // direct visible
  REP(i,n) if (intersectSS2(L(p,q),pl[i])) return 0;
  return 1;
}

bool isVisibleUsingReflection(const P &p) {    // visible from c
  // direct
  if (isVisible(c,p)) return 1;
  L l(c,p);  
  // reflect
  REP(j,n) {                
    if (ccw(pl[j][0], pl[j][1], c) * ccw(pl[j][0], pl[j][1], p) != 1) continue;
    double d1 = distanceLP(pl[j],c);
    double d2 = distanceLP(pl[j],p);
    P refp = P(d2/(d1+d2),0) * projection(pl[j],c) + P(d1/(d1+d2),0) * projection(pl[j],p);
    if (!intersectSP(pl[j], refp)) continue;
    if (isVisible(c,refp) && isVisible(refp,p)) return 1;
  }
  return 0;
}

L reflect(const L &h, const L &l) {
  P refp = crosspoint(h,l);
  P v = refp - reflection(l,h[0]);
  return L(refp,refp+v);
}

int main() {
  while(cin >> n, n) {
    P p[20];
    REP(i,n) {
      cin >> p[i].real() >> p[i].imag();
    }
    REP(i,n) {
      pl[i] = L(p[i],p[(i+1)%n]);      
    }
    cin >> c.real() >> c.imag();
    REP(i,n) v[i].clear();
    
    REP(i,n) {
      bool ok = 1;
      if (isVisible(c,p[i])) {
        L h = L(c,p[i]);        
        // c -> p[i]
        func(h); 
        // c -> p[i] -> reflection
        int ref_id = mostNearest(h);
        if (ref_id != -1) {
          // reflect at pl[ref_id]
          func(reflect(h, pl[ref_id]));
        }
      }
      // c -> pl[j] -> p[i]
      REP(j,n) {                
        if (ccw(pl[j][0], pl[j][1], c) * ccw(pl[j][0], pl[j][1], p[i]) != 1) continue; // different side
        double d1 = distanceLP(pl[j],c);
        double d2 = distanceLP(pl[j],p[i]);
        P refp = P(d2/(d1+d2),0) * projection(pl[j],c) + P(d1/(d1+d2),0) * projection(pl[j],p[i]);
        if (!intersectSP(pl[j], refp)) continue;
        if (isVisible(c,refp)) func(L(refp,p[i]));
      }
      // reflect at corners of pl[i]
      {
        P refp = pl[i][0];
        if (isVisible(c,refp)) {
          func(reflect(L(c,refp),pl[i]));
        }
      }
      {
        P refp = pl[i][1];
        if (isVisible(c,refp)) {
          func(reflect(L(c,refp),pl[i]));
        }
      }
    }
    double ans = 0;
    REP(i,n) {
      // cout << i << endl;
      // FOR(it, v[i]) {
      //   cout << *it << endl;
      // }
      double len = abs(pl[i][1]-pl[i][0]);
      vector<double> vv;
      vv.push_back(0);
      vv.push_back(len);
      FOR(it, v[i]) {
        vv.push_back(abs(*it - pl[i][0]));
      }
      sort(ALL(vv));
      REP(j,vv.size()-1) {
        double s = (vv[j]+vv[j+1])/2 / len;
        P q = (1-s)*pl[i][0] + s*pl[i][1];
        if (!isVisibleUsingReflection(q)) {
          ans += vv[j+1]-vv[j];

          double ss = vv[j]/len, tt = vv[j+1]/len;
          P p1 = (1-ss)*pl[i][0] + ss*pl[i][1];
          P p2 = (1-tt)*pl[i][0] + tt*pl[i][1];
          // cout << p1.real() << " " << p1.imag() << endl;
          // cout << p2.real() << " " << p2.imag() << endl;
          // cout << endl;
        }
      }
    }
    printf("%.10f\n", ans);
  }
}
accuracy: 1
time_ms: 40
memory_kb: 1300
final_rank: 1

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) {
  if (intersectSP(s,t[0]) || intersectSP(s,t[1]) ||
      intersectSP(t,s[0]) || intersectSP(t,s[1])) return 0;
  return intersectSS(s,t);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectLP(h,s[0]) || intersectLP(h,s[1]) ||
      intersectLP(s,h[0]) || intersectLP(s,h[1])) return 0;
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

int n;
L pl[20];
vector<P> v[20];

void func(const L &h) {
  double mi = INF;
  int cl_id = -1;
  REP(k,n) {
    if (intersectHS(h,pl[k])) {
      if (chmin(mi,norm(crosspoint(h,pl[k])-h[0]))) {
        cl_id = k;
      }
    }
  }
  if (cl_id != -1) {
    v[cl_id].push_back(crosspoint(h,pl[cl_id]));
  }
}

P c;

bool isVisible(const P &p) {
  // direct
  L l(c,p);
  bool ok = 1;
  REP(i,n) {
    ok &= !intersectSS2(l,pl[i]);
  }
  if (ok) return 1;
  // reflect
  REP(j,n) {                
    if (ccw(pl[j][0], pl[j][1], c) * ccw(pl[j][0], pl[j][1], p) != 1) continue;
    double d1 = distanceLP(pl[j],c);
    double d2 = distanceLP(pl[j],p);
    P refp = P(d2/(d1+d2),0) * projection(pl[j],c) + P(d1/(d1+d2),0) * projection(pl[j],p);
    if (!intersectSP(pl[j], refp)) continue;
    bool ok = 1;
    L l1(c,refp);
    L l2(refp,p);
    REP(k,n) {
      ok &= !intersectSS2(l1,pl[k]);
      ok &= !intersectSS2(l2,pl[k]);
    }
    if (ok) return 1;
  }
  return 0;
}

int main() {
  while(cin >> n, n) {
    P p[20];
    REP(i,n) {
      cin >> p[i].real() >> p[i].imag();
    }
    REP(i,n) {
      pl[i] = L(p[i],p[(i+1)%n]);      
    }
    cin >> c.real() >> c.imag();
    REP(i,n) v[i].clear();
    
    REP(i,n) {
      bool ok = 1;
      L l1 = L(c,p[i]);
      REP(k,n) ok &= !intersectSS2(l1,pl[k]);
      if (ok) {
        // c -> p[i]
        func(l1); 
        // c -> p[i] -> reflection
        int ref_id = -1;
        double mi = INF;
        REP(j,n) {
          if (intersectHS(l1,pl[j])) {
            if (chmin(mi, norm(crosspoint(l1,pl[j])-c))) {
              ref_id = j;
            }
          }
        }
        if (ref_id != -1) {
          // reflect at pl[ref_id]
          P refp = crosspoint(l1,pl[ref_id]);
          P v = refp - reflection(pl[ref_id],c);
          func(L(refp, refp+v));
        }
      }
      // c -> pl[j] -> p[i]
      REP(j,n) {                
        if (ccw(pl[j][0], pl[j][1], c) * ccw(pl[j][0], pl[j][1], p[i]) != 1) continue;
        double d1 = distanceLP(pl[j],c);
        double d2 = distanceLP(pl[j],p[i]);
        P refp = P(d2/(d1+d2),0) * projection(pl[j],c) + P(d1/(d1+d2),0) * projection(pl[j],p[i]);
        if (!intersectSP(pl[j], refp)) continue;
        bool ok = 1;
        L l1(c,refp);
        L l2(refp,p[i]);
        REP(k,n) {
          ok &= !intersectSS2(l1,pl[k]);
        }
        if (!ok) continue;

        func(l2);
      }
      // reflect at corners of pl[i]
      {
        P refp = pl[i][0];
        L l1(c,refp);
        bool ok = 1;        
        REP(k,n) ok &= !intersectSS2(l1,pl[k]);
        if (ok) {
          L l2 = L(refp, refp + refp-reflection(pl[i], c));          
          func(l2);
        }
      }
      {
        P refp = pl[i][1];
        L l1(c,refp);
        bool ok = 1;        
        REP(k,n) ok &= !intersectSS2(l1,pl[k]);
        if (ok) {
          L l2 = L(refp, refp + refp-reflection(pl[i], c));
          func(l2);
        }        
      }
    }
    double ans = 0;
    REP(i,n) {
      // cout << i << endl;
      // FOR(it, v[i]) {
      //   cout << *it << endl;
      // }
      double len = abs(pl[i][1]-pl[i][0]);
      vector<double> vv;
      vv.push_back(0);
      vv.push_back(len);
      FOR(it, v[i]) {
        vv.push_back(abs(*it - pl[i][0]));
      }
      sort(ALL(vv));
      REP(j,vv.size()-1) {
        double s = (vv[j]+vv[j+1])/2 / len;
        P q = (1-s)*pl[i][0] + s*pl[i][1];
        if (!isVisible(q)) {
          ans += vv[j+1]-vv[j];

          double ss = vv[j]/len, tt = vv[j+1]/len;
          P p1 = (1-ss)*pl[i][0] + ss*pl[i][1];
          P p2 = (1-tt)*pl[i][0] + tt*pl[i][1];
          // cout << p1.real() << " " << p1.imag() << endl;
          // cout << p2.real() << " " << p2.imag() << endl;
          // cout << endl;
        }
      }
    }
    printf("%.10f\n", ans);
  }
}
accuracy: 1
time_ms: 40
memory_kb: 1300
final_rank: 1