#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <iomanip>
using namespace std;
ifstream F("robot.in");
ofstream G("robot.out");
const double eps = 1e-9;
const int infi = 1<<30;
const int debuging = 0;
#define x first
#define y second
typedef pair<int,int> pi;
typedef pair<double,double> pd;
pi finish;
vector<pi> robot;
vector< vector<pi> > obstacle;
int ecu(pi A,pi B,pi C)
{
int a = A.y - B.y;
int b = B.x - A.x;
int c = - A.y * B.x + B.y * A.x;
int d = a * C.x + b * C.y + c;
return d > 0 ? 1 : ( d < 0 ? -1 : 0 );
}
int segment(pi A,pi B,pi C)
{
if ( ecu(A,B,C) ) return 0;
if ( min(A.x,B.x) > C.x || C.x > max(A.x,B.x) ) return 0;
if ( min(A.y,B.y) > C.y || C.y > max(A.y,B.y) ) return 0;
return 1;
}
void print_vector(vector<pi> V)
{
if ( debuging == 0 ) return;
G<<"debug: ";
for (vector<pi>::iterator it=V.begin();it!=V.end();++it)
G<<'('<<it->x<<","<<it->y<<") ";
G<<"\n";
}
void cprint_vector(vector<pi> V)
{
if ( debuging == 0 ) return;
cout<<"debug: ";
for (vector<pi>::iterator it=V.begin();it!=V.end();++it)
cout<<'('<<it->x<<","<<it->y<<") ";
cout<<"\n";
}
void print_array(double A[],int sz)
{
if ( debuging == 0 ) return;
G<<"debug: ";
for (int i=0;i<sz;++i)
{
if ( max(A[i]-infi,infi-A[i]) < eps ) G<<"infi "; else
G<<fixed<<setprecision(2)<<A[i]<<" ";
}
G<<"\n";
}
void read()
{
int N=0,M=0;
F>>N;
for (int i=1,x,y;i<=N;++i)
{
F>>x>>y;
robot.push_back( make_pair(x,y) );
}
F>>M;
for (int i=1;i<=M;++i)
{
vector<pi> act;
F>>N;
for (int j=1,x,y;j<=N;++j)
{
F>>x>>y;
act.push_back( make_pair(x,y) );
}
obstacle.push_back( act );
}
F>>finish.x>>finish.y;
}
pi trans(pi a,pi t,pi o)
{
return make_pair( a.x - o.x + t.x , a.y - o.y + t.y );
}
void convex_hull(vector<pi>& A)
{
sort(A.begin(),A.end());
A.erase( unique( A.begin(),A.end() ) , A.end() );
vector<pi> out;
vector<pi> stack;
int N = A.size();
for (int i=0;i<N;++i)
if ( ecu(A[0],A[N-1],A[i]) >= 0 )
{
if ( stack.size() > 1 )
while ( ecu( stack[stack.size()-2] , A[i] , stack[stack.size()-1] ) <= 0 )
{
stack.pop_back();
if ( stack.size() < 2 ) break;
}
stack.push_back(A[i]);
cprint_vector(stack);
}
while ( !stack.empty() )
{
stack.pop_back();
if ( !stack.empty() )
out.push_back( stack.back() );
}
for (int i=N-1;i>=0;--i)
if ( ecu(A[N-1],A[0],A[i]) >= 0 )
{
if ( stack.size() > 1 )
while ( ecu( stack[stack.size()-2] , A[i] , stack[stack.size()-1] ) <= 0 )
{
stack.pop_back();
if ( stack.size() < 2 ) break;
}
stack.push_back(A[i]);
if ( debuging ) cprint_vector(stack);
}
while ( !stack.empty() )
{
stack.pop_back();
if ( !stack.empty() )
out.push_back( stack.back() );
}
A = out;
}
void expand()
{
sort(robot.begin(),robot.end());
for (size_t i=0;i<obstacle.size();++i)
{
int size = obstacle[i].size();
for (int j=0;j<size;++j)
for (size_t k=0;k<robot.size();++k)
obstacle[i].push_back( trans(obstacle[i][j],robot[0],robot[k]) );
convex_hull( obstacle[i] );
if ( debuging ) print_vector( obstacle[i] );
}
}
void placef()
{
int miny = robot[0].y;
for (size_t i=1;i<robot.size();++i)
miny = min(miny,robot[i].y);
finish.y += robot[0].y-miny;
}
double dist(pi A,pi B)
{
return sqrt( (A.x-B.x) * (A.x-B.x) + (A.y-B.y) * (A.y-B.y) );
}
int next(int i,int s)
{
return i+1 < s ? i+1 : 0;
}
int cross(pi a,pi b)
{
return a.x * b.y - a.y * b.x;
}
int area(vector<pi> v)
{
int out = 0;
for (size_t i=0;i<v.size()-1;++i)
out += cross(v[i],v[i+1]);
out = max(out,-out);
return out;
}
int tarea(pi A,pi B,pi C)
{
int out = cross(A,B) + cross(B,C) + cross(C,A);
out = max(out,-out);
return out;
}
int parea(vector<pi> v,pi a)
{
int out = 0;
for (size_t i=0;i<v.size()-1;++i)
out += tarea(v[i],v[i+1],a);
return out;
}
pd internow;
int int2(pi A,pi B,pi C,pi D)
{
double a1 = A.y - B.y;
double b1 = B.x - A.x;
double c1 = - A.y * B.x + B.y * A.x;
double a2 = C.y - D.y;
double b2 = D.x - C.x;
double c2 = - C.y * D.x + D.y * C.x;
double d = a1*b2 - b1*a2;
if ( d == 0 )
return 0;
else
{
internow = make_pair( (b2*c1-b1*c2)/d , (a1*c2-a2*c1)/d );
return ecu(C,B,A)*ecu(D,B,A)<=0 && ecu(A,C,D)*ecu(B,C,D)<=0;
}
}
bool intersection(pi A,pi B,vector<pi> V)
{
int N = V.size();
V.push_back(V[0]);
for (int i=0;i<N;++i)
if ( ecu(A,V[i],V[i+1]) == 0 && ecu(B,V[i],V[i+1]) == 0 )
return 0;
int a=0,b=0;
for (int i=0;i<N;++i)
{
if ( segment(V[i],V[i+1],A) ) a = 1;
if ( segment(V[i],V[i+1],B) ) b = 1;
}
if ( a && b ) return 1;
int area_v = area(V);
int area_a = parea(V,A);
int area_b = parea(V,B);
if ( area_v == area_a && a == 0 ) return 1;
if ( area_v == area_b && b == 0 ) return 1;
vector<pd> inter;
for (int i=0;i<N;++i)
if ( int2(A,B,V[i],V[i+1]) )
inter.push_back( internow );
sort(inter.begin(),inter.end());
inter.erase(unique(inter.begin(),inter.end()),inter.end());
return inter.size() > 1;
}
double distancee(pi A,pi B)
{
if ( A == B ) return 0;
double out = dist(A,B);
for (vector< vector<pi> >::iterator vect=obstacle.begin();vect!=obstacle.end();++vect)
if ( intersection(A,B,*vect) )
return infi;
return out;
}
void solve()
{
vector<pi> points;
points.push_back( robot[0] );
for (vector< vector<pi> >::iterator vect=obstacle.begin();vect!=obstacle.end();++vect)
for (vector<pi>::iterator it=vect->begin();it!=vect->end();++it)
points.push_back(*it);
points.push_back( finish );
int N = points.size();
double cost[N+10][N+10];
for (int i=0;i<N;++i)
for (int j=0;j<N;++j)
cost[i][j] = distancee(points[i],points[j]);
for (int i=0;i<N;++i)
print_array( cost[i],N );
double d[N+10];
for (int i=0;i<N;++i)
d[i] = infi;
d[0] = 0;
queue<int> Q;
Q.push(0);
if ( debuging ) G<<"\n";
while ( Q.size() )
{
int node = Q.front();
Q.pop();
for (int i=0;i<N;++i)
if ( d[node] + cost[node][i] < d[i] - eps )
{
Q.push( i );
d[i] = d[node] + cost[node][i];
}
print_array(d,N);
}
G<<fixed<<setprecision(3)<<d[N-1]<<'\n';
}
int main()
{
read();
expand();
placef();
solve();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnN0cmVhbT4KI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8cXVldWU+CiNpbmNsdWRlIDxpb21hbmlwPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKaWZzdHJlYW0gRigicm9ib3QuaW4iKTsKb2ZzdHJlYW0gRygicm9ib3Qub3V0Iik7Cgpjb25zdCBkb3VibGUgZXBzID0gMWUtOTsKY29uc3QgaW50IGluZmkgPSAxPDwzMDsKY29uc3QgaW50IGRlYnVnaW5nID0gMDsKCiNkZWZpbmUgeCBmaXJzdAojZGVmaW5lIHkgc2Vjb25kCgp0eXBlZGVmIHBhaXI8aW50LGludD4gcGk7CnR5cGVkZWYgcGFpcjxkb3VibGUsZG91YmxlPiBwZDsKCnBpIGZpbmlzaDsKdmVjdG9yPHBpPiByb2JvdDsKdmVjdG9yPCB2ZWN0b3I8cGk+ID4gb2JzdGFjbGU7CgppbnQgZWN1KHBpIEEscGkgQixwaSBDKQp7CiAgICBpbnQgYSA9IEEueSAtIEIueTsKICAgIGludCBiID0gQi54IC0gQS54OwogICAgaW50IGMgPSAtIEEueSAqIEIueCArIEIueSAqIEEueDsKICAgIGludCBkID0gYSAqIEMueCArIGIgKiBDLnkgKyBjOwogICAgcmV0dXJuIGQgPiAwID8gMSA6ICggZCA8IDAgPyAtMSA6IDAgKTsKfQoKaW50IHNlZ21lbnQocGkgQSxwaSBCLHBpIEMpCnsKICAgIGlmICggZWN1KEEsQixDKSApIHJldHVybiAwOwogICAgaWYgKCBtaW4oQS54LEIueCkgPiBDLnggfHwgQy54ID4gbWF4KEEueCxCLngpICkgcmV0dXJuIDA7CiAgICBpZiAoIG1pbihBLnksQi55KSA+IEMueSB8fCBDLnkgPiBtYXgoQS55LEIueSkgKSByZXR1cm4gMDsKICAgIHJldHVybiAxOwp9Cgp2b2lkIHByaW50X3ZlY3Rvcih2ZWN0b3I8cGk+IFYpCnsKICAgIGlmICggZGVidWdpbmcgPT0gMCApIHJldHVybjsKICAgIEc8PCJkZWJ1ZzogIjsKICAgIGZvciAodmVjdG9yPHBpPjo6aXRlcmF0b3IgaXQ9Vi5iZWdpbigpO2l0IT1WLmVuZCgpOysraXQpCiAgICAgICAgRzw8JygnPDxpdC0+eDw8IiwiPDxpdC0+eTw8IikgIjsKICAgIEc8PCJcbiI7Cn0KCnZvaWQgY3ByaW50X3ZlY3Rvcih2ZWN0b3I8cGk+IFYpCnsKICAgIGlmICggZGVidWdpbmcgPT0gMCApIHJldHVybjsKICAgIGNvdXQ8PCJkZWJ1ZzogIjsKICAgIGZvciAodmVjdG9yPHBpPjo6aXRlcmF0b3IgaXQ9Vi5iZWdpbigpO2l0IT1WLmVuZCgpOysraXQpCiAgICAgICAgY291dDw8JygnPDxpdC0+eDw8IiwiPDxpdC0+eTw8IikgIjsKICAgIGNvdXQ8PCJcbiI7Cn0KCnZvaWQgcHJpbnRfYXJyYXkoZG91YmxlIEFbXSxpbnQgc3opCnsKICAgIGlmICggZGVidWdpbmcgPT0gMCApIHJldHVybjsKICAgIEc8PCJkZWJ1ZzogIjsKICAgIGZvciAoaW50IGk9MDtpPHN6OysraSkKICAgIHsKICAgICAgICBpZiAoIG1heChBW2ldLWluZmksaW5maS1BW2ldKSA8IGVwcyApIEc8PCJpbmZpICI7IGVsc2UKICAgICAgICBHPDxmaXhlZDw8c2V0cHJlY2lzaW9uKDIpPDxBW2ldPDwiICI7CiAgICB9CiAgICBHPDwiXG4iOwp9Cgp2b2lkIHJlYWQoKQp7CiAgICBpbnQgTj0wLE09MDsKICAgIEY+Pk47CiAgICBmb3IgKGludCBpPTEseCx5O2k8PU47KytpKQogICAgewogICAgICAgIEY+Png+Pnk7CiAgICAgICAgcm9ib3QucHVzaF9iYWNrKCBtYWtlX3BhaXIoeCx5KSApOwogICAgfQogICAgRj4+TTsKICAgIGZvciAoaW50IGk9MTtpPD1NOysraSkKICAgIHsKICAgICAgICB2ZWN0b3I8cGk+IGFjdDsKICAgICAgICBGPj5OOwogICAgICAgIGZvciAoaW50IGo9MSx4LHk7ajw9TjsrK2opCiAgICAgICAgewogICAgICAgICAgICBGPj54Pj55OwogICAgICAgICAgICBhY3QucHVzaF9iYWNrKCBtYWtlX3BhaXIoeCx5KSApOwogICAgICAgIH0KICAgICAgICBvYnN0YWNsZS5wdXNoX2JhY2soIGFjdCApOwogICAgfQogICAgRj4+ZmluaXNoLng+PmZpbmlzaC55Owp9CgpwaSB0cmFucyhwaSBhLHBpIHQscGkgbykKewogICAgcmV0dXJuIG1ha2VfcGFpciggYS54IC0gby54ICsgdC54ICwgYS55IC0gby55ICsgdC55ICk7Cn0KCnZvaWQgY29udmV4X2h1bGwodmVjdG9yPHBpPiYgQSkKewogICAgc29ydChBLmJlZ2luKCksQS5lbmQoKSk7CiAgICBBLmVyYXNlKCB1bmlxdWUoIEEuYmVnaW4oKSxBLmVuZCgpICkgLCBBLmVuZCgpICk7CiAgICB2ZWN0b3I8cGk+IG91dDsKICAgIHZlY3RvcjxwaT4gc3RhY2s7CiAgICBpbnQgTiA9IEEuc2l6ZSgpOwoKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgIGlmICggZWN1KEFbMF0sQVtOLTFdLEFbaV0pID49IDAgKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKCBzdGFjay5zaXplKCkgPiAxICkKICAgICAgICAgICAgICAgIHdoaWxlICggZWN1KCBzdGFja1tzdGFjay5zaXplKCktMl0gLCBBW2ldICwgc3RhY2tbc3RhY2suc2l6ZSgpLTFdICkgPD0gMCApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgc3RhY2sucG9wX2JhY2soKTsKICAgICAgICAgICAgICAgICAgICBpZiAoIHN0YWNrLnNpemUoKSA8IDIgKSBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RhY2sucHVzaF9iYWNrKEFbaV0pOwogICAgICAgICAgICBjcHJpbnRfdmVjdG9yKHN0YWNrKTsKICAgICAgICB9CiAgICB3aGlsZSAoICFzdGFjay5lbXB0eSgpICkKICAgIHsKICAgICAgICBzdGFjay5wb3BfYmFjaygpOwogICAgICAgIGlmICggIXN0YWNrLmVtcHR5KCkgKQogICAgICAgICAgICBvdXQucHVzaF9iYWNrKCBzdGFjay5iYWNrKCkgKTsKICAgIH0KCiAgICBmb3IgKGludCBpPU4tMTtpPj0wOy0taSkKICAgICAgICBpZiAoIGVjdShBW04tMV0sQVswXSxBW2ldKSA+PSAwICkKICAgICAgICB7CiAgICAgICAgICAgIGlmICggc3RhY2suc2l6ZSgpID4gMSApCiAgICAgICAgICAgICAgICB3aGlsZSAoIGVjdSggc3RhY2tbc3RhY2suc2l6ZSgpLTJdICwgQVtpXSAsIHN0YWNrW3N0YWNrLnNpemUoKS0xXSApIDw9IDAgKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHN0YWNrLnBvcF9iYWNrKCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKCBzdGFjay5zaXplKCkgPCAyICkgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIHN0YWNrLnB1c2hfYmFjayhBW2ldKTsKICAgICAgICAgICAgaWYgKCBkZWJ1Z2luZyApIGNwcmludF92ZWN0b3Ioc3RhY2spOwogICAgICAgIH0KICAgIHdoaWxlICggIXN0YWNrLmVtcHR5KCkgKQogICAgewogICAgICAgIHN0YWNrLnBvcF9iYWNrKCk7CiAgICAgICAgaWYgKCAhc3RhY2suZW1wdHkoKSApCiAgICAgICAgICAgIG91dC5wdXNoX2JhY2soIHN0YWNrLmJhY2soKSApOwogICAgfQoKICAgIEEgPSBvdXQ7Cn0KCnZvaWQgZXhwYW5kKCkKewogICAgc29ydChyb2JvdC5iZWdpbigpLHJvYm90LmVuZCgpKTsKICAgIGZvciAoc2l6ZV90IGk9MDtpPG9ic3RhY2xlLnNpemUoKTsrK2kpCiAgICB7CiAgICAgICAgaW50IHNpemUgPSBvYnN0YWNsZVtpXS5zaXplKCk7CiAgICAgICAgZm9yIChpbnQgaj0wO2o8c2l6ZTsrK2opCiAgICAgICAgICAgIGZvciAoc2l6ZV90IGs9MDtrPHJvYm90LnNpemUoKTsrK2spCiAgICAgICAgICAgICAgICBvYnN0YWNsZVtpXS5wdXNoX2JhY2soIHRyYW5zKG9ic3RhY2xlW2ldW2pdLHJvYm90WzBdLHJvYm90W2tdKSApOwogICAgICAgIGNvbnZleF9odWxsKCBvYnN0YWNsZVtpXSApOwogICAgICAgIGlmICggZGVidWdpbmcgKSBwcmludF92ZWN0b3IoIG9ic3RhY2xlW2ldICk7CiAgICB9Cn0KCnZvaWQgcGxhY2VmKCkKewogICAgaW50IG1pbnkgPSByb2JvdFswXS55OwogICAgZm9yIChzaXplX3QgaT0xO2k8cm9ib3Quc2l6ZSgpOysraSkKICAgICAgICBtaW55ID0gbWluKG1pbnkscm9ib3RbaV0ueSk7CiAgICBmaW5pc2gueSArPSByb2JvdFswXS55LW1pbnk7Cn0KCmRvdWJsZSBkaXN0KHBpIEEscGkgQikKewogICAgcmV0dXJuIHNxcnQoIChBLngtQi54KSAqIChBLngtQi54KSArIChBLnktQi55KSAqIChBLnktQi55KSApOwp9CgppbnQgbmV4dChpbnQgaSxpbnQgcykKewogICAgcmV0dXJuIGkrMSA8IHMgPyBpKzEgOiAwOwp9CgppbnQgY3Jvc3MocGkgYSxwaSBiKQp7CiAgICByZXR1cm4gYS54ICogYi55IC0gYS55ICogYi54Owp9CgppbnQgYXJlYSh2ZWN0b3I8cGk+IHYpCnsKICAgIGludCBvdXQgPSAwOwogICAgZm9yIChzaXplX3QgaT0wO2k8di5zaXplKCktMTsrK2kpCiAgICAgICAgb3V0ICs9IGNyb3NzKHZbaV0sdltpKzFdKTsKICAgIG91dCA9IG1heChvdXQsLW91dCk7CiAgICByZXR1cm4gb3V0Owp9CgppbnQgdGFyZWEocGkgQSxwaSBCLHBpIEMpCnsKICAgIGludCBvdXQgPSBjcm9zcyhBLEIpICsgY3Jvc3MoQixDKSArIGNyb3NzKEMsQSk7CiAgICBvdXQgPSBtYXgob3V0LC1vdXQpOwogICAgcmV0dXJuIG91dDsKfQoKaW50IHBhcmVhKHZlY3RvcjxwaT4gdixwaSBhKQp7CiAgICBpbnQgb3V0ID0gMDsKICAgIGZvciAoc2l6ZV90IGk9MDtpPHYuc2l6ZSgpLTE7KytpKQogICAgICAgIG91dCArPSB0YXJlYSh2W2ldLHZbaSsxXSxhKTsKICAgIHJldHVybiBvdXQ7Cn0KCnBkIGludGVybm93OwoKaW50IGludDIocGkgQSxwaSBCLHBpIEMscGkgRCkKewogICAgZG91YmxlIGExID0gQS55IC0gQi55OwogICAgZG91YmxlIGIxID0gQi54IC0gQS54OwogICAgZG91YmxlIGMxID0gLSBBLnkgKiBCLnggKyBCLnkgKiBBLng7CgogICAgZG91YmxlIGEyID0gQy55IC0gRC55OwogICAgZG91YmxlIGIyID0gRC54IC0gQy54OwogICAgZG91YmxlIGMyID0gLSBDLnkgKiBELnggKyBELnkgKiBDLng7CgogICAgZG91YmxlIGQgPSBhMSpiMiAtIGIxKmEyOwogICAgaWYgKCBkID09IDAgKQogICAgICAgIHJldHVybiAwOwogICAgZWxzZQogICAgewogICAgICAgIGludGVybm93ID0gbWFrZV9wYWlyKCAoYjIqYzEtYjEqYzIpL2QgLCAoYTEqYzItYTIqYzEpL2QgKTsKICAgICAgICByZXR1cm4gZWN1KEMsQixBKSplY3UoRCxCLEEpPD0wICYmIGVjdShBLEMsRCkqZWN1KEIsQyxEKTw9MDsKICAgIH0KfQoKYm9vbCBpbnRlcnNlY3Rpb24ocGkgQSxwaSBCLHZlY3RvcjxwaT4gVikKewogICAgaW50IE4gPSBWLnNpemUoKTsKICAgIFYucHVzaF9iYWNrKFZbMF0pOwoKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgIGlmICggZWN1KEEsVltpXSxWW2krMV0pID09IDAgJiYgZWN1KEIsVltpXSxWW2krMV0pID09IDAgKQogICAgICAgICAgICByZXR1cm4gMDsKCiAgICBpbnQgYT0wLGI9MDsKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgewogICAgICAgIGlmICggc2VnbWVudChWW2ldLFZbaSsxXSxBKSApIGEgPSAxOwogICAgICAgIGlmICggc2VnbWVudChWW2ldLFZbaSsxXSxCKSApIGIgPSAxOwogICAgfQoKICAgIGlmICggYSAmJiBiICkgcmV0dXJuIDE7CgogICAgaW50IGFyZWFfdiA9IGFyZWEoVik7CiAgICBpbnQgYXJlYV9hID0gcGFyZWEoVixBKTsKICAgIGludCBhcmVhX2IgPSBwYXJlYShWLEIpOwoKICAgIGlmICggYXJlYV92ID09IGFyZWFfYSAmJiBhID09IDAgKSByZXR1cm4gMTsKICAgIGlmICggYXJlYV92ID09IGFyZWFfYiAmJiBiID09IDAgKSByZXR1cm4gMTsKCiAgICB2ZWN0b3I8cGQ+IGludGVyOwogICAgZm9yIChpbnQgaT0wO2k8TjsrK2kpCiAgICAgICAgaWYgKCBpbnQyKEEsQixWW2ldLFZbaSsxXSkgKQogICAgICAgICAgICBpbnRlci5wdXNoX2JhY2soIGludGVybm93ICk7CgogICAgc29ydChpbnRlci5iZWdpbigpLGludGVyLmVuZCgpKTsKICAgIGludGVyLmVyYXNlKHVuaXF1ZShpbnRlci5iZWdpbigpLGludGVyLmVuZCgpKSxpbnRlci5lbmQoKSk7CgogICAgcmV0dXJuIGludGVyLnNpemUoKSA+IDE7Cn0KCmRvdWJsZSBkaXN0YW5jZWUocGkgQSxwaSBCKQp7CiAgICBpZiAoIEEgPT0gQiApIHJldHVybiAwOwogICAgZG91YmxlIG91dCA9IGRpc3QoQSxCKTsKICAgIGZvciAodmVjdG9yPCB2ZWN0b3I8cGk+ID46Oml0ZXJhdG9yIHZlY3Q9b2JzdGFjbGUuYmVnaW4oKTt2ZWN0IT1vYnN0YWNsZS5lbmQoKTsrK3ZlY3QpCiAgICAgICAgaWYgKCBpbnRlcnNlY3Rpb24oQSxCLCp2ZWN0KSApCiAgICAgICAgICAgIHJldHVybiBpbmZpOwogICAgcmV0dXJuIG91dDsKfQoKdm9pZCBzb2x2ZSgpCnsKICAgIHZlY3RvcjxwaT4gcG9pbnRzOwogICAgcG9pbnRzLnB1c2hfYmFjayggcm9ib3RbMF0gKTsKICAgIGZvciAodmVjdG9yPCB2ZWN0b3I8cGk+ID46Oml0ZXJhdG9yIHZlY3Q9b2JzdGFjbGUuYmVnaW4oKTt2ZWN0IT1vYnN0YWNsZS5lbmQoKTsrK3ZlY3QpCiAgICAgICAgZm9yICh2ZWN0b3I8cGk+OjppdGVyYXRvciBpdD12ZWN0LT5iZWdpbigpO2l0IT12ZWN0LT5lbmQoKTsrK2l0KQogICAgICAgICAgICBwb2ludHMucHVzaF9iYWNrKCppdCk7CiAgICBwb2ludHMucHVzaF9iYWNrKCBmaW5pc2ggKTsKCiAgICBpbnQgTiA9IHBvaW50cy5zaXplKCk7CiAgICBkb3VibGUgY29zdFtOKzEwXVtOKzEwXTsKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgIGZvciAoaW50IGo9MDtqPE47KytqKQogICAgICAgICAgICBjb3N0W2ldW2pdID0gZGlzdGFuY2VlKHBvaW50c1tpXSxwb2ludHNbal0pOwoKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgIHByaW50X2FycmF5KCBjb3N0W2ldLE4gKTsKCiAgICBkb3VibGUgZFtOKzEwXTsKICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgIGRbaV0gPSBpbmZpOwoKICAgIGRbMF0gPSAwOwogICAgcXVldWU8aW50PiBROwogICAgUS5wdXNoKDApOwoKICAgIGlmICggZGVidWdpbmcgKSBHPDwiXG4iOwoKICAgIHdoaWxlICggUS5zaXplKCkgKQogICAgewogICAgICAgIGludCBub2RlID0gUS5mcm9udCgpOwogICAgICAgIFEucG9wKCk7CgogICAgICAgIGZvciAoaW50IGk9MDtpPE47KytpKQogICAgICAgICAgICBpZiAoIGRbbm9kZV0gKyBjb3N0W25vZGVdW2ldIDwgZFtpXSAtIGVwcyApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIFEucHVzaCggaSApOwogICAgICAgICAgICAgICAgZFtpXSA9IGRbbm9kZV0gKyBjb3N0W25vZGVdW2ldOwogICAgICAgICAgICB9CiAgICAgICAgcHJpbnRfYXJyYXkoZCxOKTsKICAgIH0KCiAgICBHPDxmaXhlZDw8c2V0cHJlY2lzaW9uKDMpPDxkW04tMV08PCdcbic7Cn0KCmludCBtYWluKCkKewogICAgcmVhZCgpOwogICAgZXhwYW5kKCk7CiAgICBwbGFjZWYoKTsKICAgIHNvbHZlKCk7Cn0K