Language: C++

#include<iostream>
#include<complex>
#include<algorithm>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back
#define ALL(C)     (C).begin(),(C).end()
#define mp         make_pair

typedef complex<double> P;
const double eps = 1e-10;

namespace std{
  bool operator<(const P &a,const P&b){
    if (!(fabs(a.real()-b.real())<eps))return a.real()<b.real();
    else return a.imag() < b.imag();
  }
  bool operator==(const P&a,const P&b){
    return fabs(a.real()-b.real())<eps && fabs(a.imag()-b.imag()) < eps;
  }
}

double dot(P a,P b){
  return a.real()*b.real()+a.imag()*b.imag();
}

double cross(P a,P b){
  return a.real()*b.imag()-a.imag()*b.real();
}

P symmetric_point(P o,P p,P q){
  P N=p-o,L=q-o;
  double t = abs(L);
  N/=abs(N);
  L/=abs(L);
  double prepL = dot(N,L);//theta element of vector L against N (|L|=|N|=1
  double d=2*prepL;
  P r(d*N - L);//R vector symmetric point of L
  return o+t*r;
}

bool isp(P &a,P &b,P &c){
  return abs(a-c)+abs(b-c) <abs(a-b) + eps;
}

P intersection_ll(P a1,P a2,P b1,P b2){
  P a= a2-a1,b=b2-b1;
  return a1+ a*cross(b,b1-a1)/cross(b,a);
}

bool is_in(vector<P>& in,P a){
  int cnt =0;
  int n = in.size();
  rep(i,n){
    P cur = in[i]-a,next=in[(i+1)%n]-a;
    if (cur.imag() > next.imag())swap(cur,next);
    if (cur.imag()<0 && 0<=next.imag() &&
	cross(next,cur)>=0)cnt++;
    if (isp(in[i],in[(i+1)%n],a))return true;
  }
  if (cnt %2 == 1)return true;
  else return false;
}

void find_onp(vector<P> &in,vector<P> &ori,P &a,P &b,vector<P> &ret,
	      bool issym,P &sa,P &sb){
  vector<P> tret;
  vector<P> inside;inside.pb(a);inside.pb(b);
  tret.pb(a);
  tret.pb(b);
  rep(i,in.size()){
    P tmp = intersection_ll(a,b,in[i],in[(i+1)%in.size()]);
    if (dot(b-a,tmp-a)<eps);
    else if (isp(in[i],in[(i+1)%in.size()],tmp) 
	     //&&isp(a,b,tmp)
	     )tret.pb(tmp);

    tmp = intersection_ll(a,b,ori[i],ori[(i+1)%ori.size()]);
    if (dot(b-a,tmp-a)<eps);
    else if (isp(ori[i],ori[(i+1)%ori.size()],tmp))inside.pb(tmp);
  }
  
  sort(ALL(inside));
  rep(i,inside.size()-1){
    if (!is_in(ori,(inside[i]+inside[i+1])/(double)2.0)&&
	!(issym&&is_in(in,(inside[i]+inside[i+1])/(double)2.0))){
      //      cout << "a b " << issym <<" " << a <<" " << inside[i] <<
      //	" " << inside[i+1]<<b<<endl;
      return;
    }
  }

  sort(ALL(tret));
  tret.erase(unique(ALL(tret)),tret.end());
  
  if (!(abs(tret[0]-a) <eps )){
    reverse(ALL(tret));
    assert(abs(tret[0]-a)<eps);
  }
    
  //  cout << "a b " << issym <<" " << a <<b<<endl;
  //  rep(i,tret.size())cout << tret[i];cout<<endl;

  rep(i,tret.size()-1){
    if (issym && i == 0)continue;
    P mid = (tret[i]+tret[i+1])/(double)2.0;
    P symmid=symmetric_point(sa,sb,mid);
    //    cout << mid <<" " << symmid << endl;
    //if (issym&&!isp(sa,sb,mid))mid=symmetric_point(sa,sb,mid);
    if (is_in(in,mid)){
      //      cout <<"ok " << tret[i+1] << endl;
      if (issym&&!isp(sa,sb,tret[i+1])){
	//	cout << tret[i+1] <<" " <<symmetric_point(sa,sb,tret[i+1])
	//	     << "sym " <<sa<<sb<<endl;
	ret.pb(symmetric_point(sa,sb,tret[i+1]));
      }else {
	//cout << tret[i+1] << endl;
	ret.pb(tret[i+1]);
      }
    }else if (issym && is_in(ori,symmid)){
      //cout << "test "<<endl;
    }
    else break;
  }
  return;
}

double solve(vector<P> &in,P light){
  vector<P> ref[in.size()];
  vector<P> online[in.size()];
  vector<pair<int,P> > all;
  vector<P> all2;
  rep(i,in.size())all.pb(mp(-1,in[i]));

  rep(i,all.size()){
    vector<P> onsome;
    find_onp(in,in,light,all[i].second,onsome,false,in[0],in[0]);
    rep(j,onsome.size()){
      rep(k,in.size()){
	if (isp(in[k],in[(k+1)%in.size()],onsome[j]))online[k].pb(onsome[j]);
      }
    }
  }
  rep(i,in.size())sort(online[i].begin(),online[i].end());
  all.clear();
  
  rep(i,in.size()){
    rep(j,online[i].size()){
      all.pb(mp(i,online[i][j]));
    }
  }

  rep(i,in.size()){
    if (online[i].size()>=2 &&
	abs(online[i][0]-online[i][online[i].size()-1])>eps);
    else continue;
    //cout << "hit " << i << endl;
    rep(j,in.size()){
      P tmp = symmetric_point(in[i],in[(i+1)%in.size()],in[j]);
      if (isp(in[i],in[(i+1)%in.size()],in[j]))ref[i].pb(in[j]);
      else ref[i].pb(tmp),all.pb(mp(i,tmp));
    }
  }
    
  rep(i,all.size()){
    vector<P> onsome;
    find_onp(ref[all[i].first],in,light,all[i].second,onsome,true,in[all[i].first],
	     in[(all[i].first+1)%in.size()]);
    rep(j,onsome.size()){
      rep(k,in.size()){
	if (isp(in[k],in[(k+1)%in.size()],onsome[j]))online[k].pb(onsome[j]);
      }
    }
  }

  
  
  
  double sum = 0,ans=0;
  rep(i,in.size())sum+=abs(in[i]-in[(i+1)%in.size()]);
  rep(i,in.size()){
    sort(ALL(online[i]));
    online[i].erase(unique(ALL(online[i])),online[i].end());
    if (online[i].size() < 2)continue;
    ans+=abs(online[i][0]-online[i][online[i].size()-1]);
  }
  
  
  /*      
  rep(i,in.size()){
    cout << "this line " << in[i] <<" " << in[(i+1)%in.size()] << endl;
    sort(ALL(online[i]));
    rep(j,online[i].size()){
      cout << online[i][j];
    }
    cout << endl<<"end "<< endl << endl;
  }
  */        

  return sum-ans;
}


main(){
  int n;
  while(cin>>n && n){
    vector<P> in(n);
    P light;
    rep(i,n)cin>>in[i].real()>>in[i].imag();
    cin>>light.real()>>light.imag();
    printf("%.4lf\n",solve(in,light));
  }
}

Compiler output:
a.cc: In function 'void find_onp(std::vector<std::complex<double> >&, std::vector<std::complex<double> >&, P&, P&, std::vector<std::complex<double> >&, bool, P&, P&)':
a.cc:100:5: error: 'assert' was not declared in this scope
  100 |     assert(abs(tret[0]-a)<eps);
      |     ^~~~~~
a.cc:5:1: note: 'assert' is defined in header '<cassert>'; this is probably fixable by adding '#include <cassert>'
    4 | #include<vector>
  +++ |+#include <cassert>
    5 | using namespace std;
a.cc: At global scope:
a.cc:206:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  206 | main(){
      | ^~~~
a.cc: In function 'int main()':
a.cc:211:16: error: no match for 'operator>>' (operand types are 'std::istream' {aka 'std::basic_istream<char>'} and 'double')
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |             ~~~^~~~~~~~~~~~~~
      |             |              |
      |             |              double
      |             std::istream {aka std::basic_istream<char>}
In file included from /usr/include/c++/14/iostream:42,
                 from a.cc:1:
/usr/include/c++/14/istream:170:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(bool&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  170 |       operator>>(bool& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:170:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'bool&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:174:7: note: candidate: 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(short int&) [with _CharT = char; _Traits = std::char_traits<char>]' (near match)
  174 |       operator>>(short& __n);
      |       ^~~~~~~~
/usr/include/c++/14/istream:174:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'short int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:177:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(short unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  177 |       operator>>(unsigned short& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:177:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'short unsigned int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:181:7: note: candidate: 'std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(int&) [with _CharT = char; _Traits = std::char_traits<char>]' (near match)
  181 |       operator>>(int& __n);
      |       ^~~~~~~~
/usr/include/c++/14/istream:181:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:184:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  184 |       operator>>(unsigned int& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:184:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'unsigned int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:188:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  188 |       operator>>(long& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:188:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'long int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:192:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  192 |       operator>>(unsigned long& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:192:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'long unsigned int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:199:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  199 |       operator>>(long long& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:199:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'long long int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:203:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long unsigned int&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  203 |       operator>>(unsigned long long& __n)
      |       ^~~~~~~~
/usr/include/c++/14/istream:203:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'long long unsigned int&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:219:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(float&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  219 |       operator>>(float& __f)
      |       ^~~~~~~~
/usr/include/c++/14/istream:219:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'float&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:223:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(double&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  223 |       operator>>(double& __f)
      |       ^~~~~~~~
/usr/include/c++/14/istream:223:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:227:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long double&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' (near match)
  227 |       operator>>(long double& __f)
      |       ^~~~~~~~
/usr/include/c++/14/istream:227:7: note:   conversion of argument 1 would be ill-formed:
a.cc:211:28: error: cannot bind non-const lvalue reference of type 'long double&' to a value of type 'double'
  211 |     rep(i,n)cin>>in[i].real()>>in[i].imag();
      |                  ~~~~~~~~~~^~
/usr/include/c++/14/istream:328:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(void*&) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
  328 |       operator>>(void*& __p)
      |       ^~~~~~~~
/usr/include/c++/14/istream:328:25: note:   no known conversion for argument 1 from 'double' to 'void*&'
  328 |       operator>>(void*& __p)
      |                  ~~~~~~~^~~
/usr/include/c++/14/istream:122:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__istream_type& (*)(__istream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]'
  122 |       operator>>(__istream_type& (*__pf)(__istream_type&))
      |       ^~~~~~~~
/usr/include/c++/14/istream:122:36: note:   no known conversion for argument 1 from 'double' to 'std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&)' {aka 'std::basic_istream<char>& (*)(std::basic_istream<char>&)'}
  122 |       operator>>(__istream_type& (*__pf)(__istream_type&))
      |                  ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/istream:126:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__ios_type& (*)(__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>; __ios_type = std::basic_ios<char>]'
  126 |       operator>>(__ios_type& (*__pf)(__ios_type&))
      |       ^~~