Problem:
Problem I:
Shy Polygons
You are given two solid polygons and their positions on the
xy
-plane. You can move one
of the two along the
x
-axis (they can overlap during the move). You cannot move it in other
directions. The goal is to place them as compactly as possible, subject to the following condition:
the distance between any point in one polygon and any point in the other must not be smaller
than a given minimum distance
L
.
We define the
width
of a placement as the difference between the maximum and the minimum
x
-coordinates of all points in the two polygons.
Your job is to write a program to calculate the minimum width of placements satisfying the
above condition.
Let's see an example. If the polygons in Figure 13 are placed with
L
= 10.0, the result will be 100. Figure 14 shows one of the optimal placements.
Input
The input consists of multiple datasets. Each dataset is given in the following format.
L
Polygon
1
Polygon
2
L
is a decimal fraction, which means the required distance of two polygons.
L
is greater than
0.1 and less than 50.0.
The format of each polygon is as follows.
n
x
1
y
1
x
2
y
2
.
.
.
x
n
y
n
n
is a positive integer, which represents the number of vertices of the polygon.
n
is greater than
2 and less than 15.
Remaining lines represent the vertices of the polygon. A vertex data line has a pair of nonneg-
ative integers which represent the
x
- and y-coordinates of a vertex.
x
- and
y
-coordinates are
separated by a single space, and
y
-coordinate is immediately followed by a newline.
x
and
y
are
less than 500.
Edges of the polygon connect vertices given in two adjacent vertex data lines, and vertices given
in the last and the first vertex data lines. You may assume that the vertices are given in the
counterclockwise order, and the contours of polygons are simple, i.e. they do not cross nor touch
themselves.
Also, you may assume that the result is not sensitive to errors. In concrete terms, for a given
pair of polygons, the minimum width is a function of the given minimum distance
l
. Let us
denote the function
w
(
l
). Then you can assume that |
w
(
L
± 10
-7
) -
w
(
L
)| < 10
-4
.
The end of the input is indicated by a line that only contains a zero. It is not a part of a dataset.
Output
The output should consist of a series of lines each containing a single decimal fraction. Each
number should indicate the minimum width for the corresponding dataset. The answer should
not have an error greater than 0.0001. You may output any number of digits after the decimal
point, provided that the above accuracy condition is satisfied.
Sample Input
10.5235
3
0 0
100 100
0 100
4
0 50
20 50
20 80
0 80
10.0
4
120 45
140 35
140 65
120 55
8
0 0
100 0
100 100
0 100
0 55
80 90
80 10
0 45
10.0
3
0 0
1 0
0 1
3
0 100
1 101
0 101
10.0
3
0 0
1 0
0 100
3
0 50
100 50
0 51
0
Output for the Sample Input
114.882476
100
1
110.5005

Submitted solutions:

code_snippet: /*
 *   Created By phyxnj@uestc
 *   Last Compiler:
 *   Sun, 29 Jul 2012 02:07:44 +0800
 */
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
#include <vector>
#include <utility>
#include <string>
#include <map>
#include <iostream>
using namespace std;
#define eps 1e-7
#define pw(x) ((x)*(x))
typedef long long LL;
struct P
{
    double x,y;
    P () {}
    P (double x,double y) : x(x),y(y) {}
    P operator - (const P & b)
    {
        return P (x-b.x,y-b.y);
    }
    double operator * (const P & b)
    {
        return x*b.y-y*b.x;
    }
    double operator & (const P & b)
    {
        return x*b.x+y*b.y;
    }
    double dorm()
    {
        return sqrt(pw(x)+pw(y));
    }
}p[300],s[300],tp[300];
int sgn(double x)
{
    return x<-eps?-1:x>eps;
}
double cal(P a,P b,P c) // 计算c到ab的最小距离
{
    int t1=sgn((c-a)&(b-a));
    int t2=sgn((c-b)&(a-b));
    if(t1>=0&&t2>=0) return fabs((a-c)*(a-b))/(a-b).dorm();
    return min((c-a).dorm(),(c-b).dorm());
}
double maybe[10000]; 
int cnt,flag;
double L;
int n,m;
void run(P a,P b,P c) // 计算要使得c与ab的最小距离为L要使c移动的距离
{
    double l=-20000,h=20000,mid1,mid2;
    for(int i=0;i<50;i++){
        mid1=(2*l+h)/3;
        mid2=(2*h+l)/3;
        double t1=cal(a,b,P(mid1,c.y));
        double t2=cal(a,b,P(mid2,c.y));
        if(sgn(t1-t2)>=0) l=mid1;
        else h=mid2;
    }
    double mid;
    l=-20000;h=mid1;
    for(int i=0;i<50;i++){
        mid=(l+h)/2;
        double t1=cal(a,b,P(mid,c.y));
        if(sgn(t1-L)>=0) l=mid;
        else h=mid;
    }
    double delta=mid-c.x;
    if(flag) delta=-delta;
    maybe[cnt++]=delta;
    l=mid1,h=20000;
    for(int i=0;i<50;i++){
        mid=(l+h)/2;
        double t1=cal(a,b,P(mid,c.y));
        if(sgn(t1-L)>=0) h=mid;
        else l=mid;
    }
    delta=mid-c.x;
    if(flag) delta=-delta;
    maybe[cnt++]=delta;
}
void creat()
{
    cnt=0;
    s[m]=s[0],p[n]=p[0];
    flag=1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            run(s[j],s[j+1],p[i]);
        }
    }
    flag=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            run(p[j],p[j+1],s[i]);
        }
    }
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++) {
            maybe[cnt++]=p[j].x-s[i].x;
        }
    }
}
int in(P a,P pt[],int n)
{
    int cnt=0;
    pt[n]=pt[0];
    for(int i=0;i<n;i++){
        P x=pt[i],y=pt[i+1];
        if(sgn(x.y-y.y)>0) swap(x,y);
        if(sgn(x.y-a.y)>=0||sgn(y.y-a.y)<0) continue;
        double t=(x-a)*(y-a);
        if(sgn(t)>0) cnt++;
    }
    return cnt&1;
}
double solve()
{
    double ans=1e10;
    for(int i=0;i<cnt;i++){
        double x=maybe[i];
//        printf("%f\n",x);
        for(int j=0;j<m;j++){
            tp[j].x=s[j].x+x;
            tp[j].y=s[j].y;
        }
        tp[m]=tp[0];
        int flag=0;
        for(int j=0;j<n;j++){
            for(int k=0;k<m;k++){
                int t1=sgn((p[j]-tp[k])*(tp[k+1]-tp[k]))*sgn((p[j+1]-tp[k])*(tp[k+1]-tp[k]));
                int t2=sgn((tp[k]-p[j])*(p[j+1]-p[j]))*sgn((tp[k+1]-p[j])*(p[j+1]-p[j]));
                if(t1<0&&t2<0) {
                    flag=1;
                    break;
                }
                double dis=min(min(cal(p[j],p[j+1],tp[k]),cal(p[j],p[j+1],tp[k+1])),min(cal(tp[k],tp[k+1],p[j]),cal(tp[k],tp[k+1],p[j+1])));
                if(dis-L<-1e-6) {
                    flag=1;
                    break;
                }
            }
        }
        if(flag) continue;
        flag=in(tp[0],p,n)||in(p[0],tp,m);
        if(flag) continue;
        double minx=1e10,maxx=-1e10;
        for(int j=0;j<m;j++){
            minx=min(minx,tp[j].x);
            maxx=max(maxx,tp[j].x);
        }
        for(int j=0;j<n;j++){
            minx=min(minx,p[j].x);
            maxx=max(maxx,p[j].x);
        }
//        printf("%f %f ************\n",maxx,minx);
        ans=min(ans,maxx-minx);
    }
    return ans;
}
int main()
{   
    P a,b,c;
    while(scanf("%lf",&L)&&sgn(L)){
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        scanf("%d",&m);
        for(int i=0;i<m;i++) scanf("%lf%lf",&s[i].x,&s[i].y);
        creat();
        printf("%f\n",solve());
    }
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 3384
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-7;

struct Point {
  double x, y;
  Point rot_ccw() const { return {-y, x}; }
  double magnitude() const { return hypot(x, y); }
  Point operator+(const Point p) const { return {x + p.x, y + p.y}; }
  Point operator-(const Point p) const { return {x - p.x, y - p.y}; }
  Point scale(const double f) const { return {x * f, y * f}; }
  Point normalize() const { return scale(1 / magnitude()); }
  double dist(const Point p) const { return hypot(x - p.x, y - p.y); }
  double operator*(const Point p) const { return x * p.x + y * p.y; }
  double cross(const Point p) const { return x * p.y - y * p.x; }
};

short orientation(const Point& o, const Point& a, const Point& b) {
  const double cross = (a - o).cross(b - o);
  return cross < 0 ? -1 : cross > 0;
}

struct SegmentHorizontalIntersections {
  virtual vector<double> intersections(const Point a, const Point b) const = 0;
};

struct Segment : SegmentHorizontalIntersections {
  const Point p, q;
  Segment(const Point p, const Point q) : p(p), q(q) {}

  double dist(const Segment s) const {
    if (intersect(s)) return 0;
    return min({dist(s.p), dist(s.q), s.dist(p), s.dist(q)});
  }
  double dist(const Point r) const {
    if ((q - p) * (r - p) <= 0) return p.dist(r);
    if ((p - q) * (r - q) <= 0) return q.dist(r);
    return fabs((q - p).cross(r - p)) / p.dist(q);
  }
  bool intersect(const Segment s) const {
    const bool o1 = orientation(p, q, s.p) * orientation(p, q, s.q) < 0;
    const bool o2 = orientation(s.p, s.q, p) * orientation(s.p, s.q, q) < 0;
    return o1 && o2;
  }
  double dist_x(const Point r) const {
    const double dy = (r.y - p.y) / (q.y - p.y);
    const double x = p.x + (dy * (q.x - p.x));
    const double res = x - r.x;
    return res;
  }
  vector<double> intersections(const Point a, const Point b) const {
    if (fabs(p.y - q.y) < EPS) return {};

    const Segment s{a, b};
    return {-s.dist_x(p), -s.dist_x(q), dist_x(a), dist_x(b)};
  }
};

struct Circle : SegmentHorizontalIntersections {
  const Point center;
  const double radius;
  Circle(const Point p, const double r) : center(p), radius(r) {}

  vector<double> intersections(Point p, Point q) const {
    p = p - center;
    q = q - center;

    vector<double> res;

    for (const Point r : vector<Point>{p, q}) {
      const double arg = radius * radius - r.y * r.y;
      if (arg < 0) continue;

      const double x = sqrt(arg);
      res.emplace_back(x - r.x);
      res.emplace_back(-x - r.x);
    }

    const Point point_on_circle = (q - p).rot_ccw().normalize().scale(radius);

    for (const Point r : vector<Point>{point_on_circle, point_on_circle.scale(-1)})
      res.emplace_back(-Segment{p, q}.dist_x(r));

    return res;
  }
};

double width(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  double a = 1e9;
  double b = -1e9;
  for (const auto p : polygon1) a = min(a, p.x);
  for (const auto p : polygon2) a = min(a, p.x);
  for (const auto p : polygon1) b = max(b, p.x);
  for (const auto p : polygon2) b = max(b, p.x);
  return b - a;
}

bool point_inside_polygon(const Point p, const vector<Segment>& polygon_edges) {
  const Segment ray{p, {1e4, 1e4 + 1e-2}};
  int intersections = 0;
  for (const Segment e : polygon_edges) intersections += e.intersect(ray);
  return intersections % 2 == 1;
}

vector<Segment> polygon_edges(const vector<Point>& polygon) {
  vector<Segment> edges;

  for (int i = 0; i < (int)polygon.size(); i++)
    edges.emplace_back(polygon[i], polygon[(i + 1) % polygon.size()]);

  return edges;
}

double polygon_distance(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  double res = 1e9;

  const vector<Segment> edges1 = polygon_edges(polygon1);
  const vector<Segment> edges2 = polygon_edges(polygon2);

  for (const Segment s : edges1) {
    if (point_inside_polygon(s.p, edges2)) return 0;
    for (const Segment r : edges2) {
      if (point_inside_polygon(r.p, edges1)) return 0;
      res = min(res, s.dist(r));
    }
  }

  return res;
}

double solve(const vector<Point>& polygon1, const vector<Point>& polygon2,
             const double L) {
  double ans = 1e9;

  vector<shared_ptr<SegmentHorizontalIntersections>> obstacles;
  set<double> x_movements;

  for (const Point circle_center : polygon1)
    obstacles.emplace_back(make_shared<Circle>(circle_center, L));

  for (const Point p : polygon1)
    obstacles.emplace_back(make_shared<Segment>(Point{p.x, 2000}, Point{p.x, -2000}));

  for (const auto [p, q] : polygon_edges(polygon1)) {
    const Point dir = (p - q).normalize().rot_ccw().scale(L);
    obstacles.emplace_back(make_shared<Segment>(p + dir, q + dir));
  }

  for (const auto& obs : obstacles) {
    for (const auto [p, q] : polygon_edges(polygon2)) {
      const vector<double> xs = obs->intersections(p, q);
      copy(xs.begin(), xs.end(), inserter(x_movements, x_movements.end()));
    }
  }

  for (const double x : x_movements) {
    vector<Point> moved = polygon2;
    for (Point& p : moved) p.x += x;
    const double distance = polygon_distance(polygon1, moved);
    if (distance >= L - EPS) ans = min(ans, width(polygon1, moved));
  }

  return ans;
}

int main() {
  double L;
  while (cin >> L && L > 0) {
    int n;
    cin >> n;
    vector<Point> polygon1(n);
    for (auto& p : polygon1) cin >> p.x >> p.y;
    cin >> n;
    vector<Point> polygon2(n);
    for (auto& p : polygon2) cin >> p.x >> p.y;

    cout << fixed << setprecision(5) << solve(polygon1, polygon2, L) << endl;
  }
}
accuracy: 1
time_ms: 90
memory_kb: 3528
final_rank: 7

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

#include <algorithm>
using namespace std;

const double EPS = 1e-7;

struct Point {
  double x, y;
  Point rot_ccw() const { return {-y, x}; }
  double magnitude() const { return hypot(x, y); }
  Point operator+(const Point p) const { return {x + p.x, y + p.y}; }
  Point operator-(const Point p) const { return {x - p.x, y - p.y}; }
  Point scale(const double f) const { return {x * f, y * f}; }
  Point normalize() const { return scale(1 / magnitude()); }
  double dist(const Point p) const { return hypot(x - p.x, y - p.y); }
  double operator*(const Point p) const { return x * p.x + y * p.y; }
  double cross(const Point p) const { return x * p.y - y * p.x; }
  Point negate() const { return {-x, -y}; }
};

short orientation(const Point& o, const Point& a, const Point& b) {
  const double cross = (a - o).cross(b - o);
  return cross < 0 ? -1 : cross > 0;
}

struct Intersection {
  virtual vector<double> intersections(const Point a, const Point b) const = 0;
};

bool inside(const double v, const double a, const double b) {
  const auto [n, m] = minmax(a, b);
  return n <= v && v <= m;
}

struct Segment : Intersection {
  Point p, q;
  Segment(const Point p, const Point q) : p(p), q(q) {}
  bool is_vertical() const { return fabs(p.x - q.x) < EPS; }
  double dist(const Segment s) const {
    if (intersect(s)) return 0;
    return min({dist(s.p), dist(s.q), s.dist(p), s.dist(q)});
  }
  double dist(const Point r) const {
    if ((q - p) * (r - p) <= 0) return p.dist(r);
    if ((p - q) * (r - q) <= 0) return q.dist(r);
    return fabs((q - p).cross(r - p)) / p.dist(q);
  }
  bool intersect(const Segment s) const {
    const short o1 = orientation(p, q, s.p);
    const short o2 = orientation(p, q, s.q);
    const short o3 = orientation(s.p, s.q, p);
    const short o4 = orientation(s.p, s.q, q);
    return o1 * o2 < 0 && o3 * o4 < 0;
  }
  optional<double> dist_x(const Point r) const {
    if (!inside(r.y, p.y, q.y)) return nullopt;
    if (is_vertical()) return p.x - r.x;

    const double yp = (r.y - p.y) / (q.y - p.y);
    const double x = p.x + (yp * (q.x - p.x));
    return x - r.x;
  }

  vector<double> intersections(const Point a, const Point b) const {
    vector<double> res;

    vector<optional<double>> candidates{Segment{a, b}.dist_x(p), Segment{a, b}.dist_x(q),
                                        dist_x(a), dist_x(b)};

    int i = 0;
    for (const auto x : candidates) {
      if (x.has_value()) {
        const double val = x.value();
        if (isnan(val)) continue;
        if (i < 2) {
          res.emplace_back(-val);
        } else {
          res.emplace_back(val);
        }
      }
      i++;
    }

    return res;
  }
};

struct Circle : Intersection {
  const Point center;
  const double radius;
  Circle(const Point p, const double r) : center(p), radius(r) {}
  vector<double> intersections(Point p, Point q) const {
    p = p - center;
    q = q - center;

    vector<double> res;

    const vector<Point> ps{p, q};

    for (const Point r : ps) {
      if (inside(r.y, -radius, radius)) {
        const double x0 = sqrt(radius * radius - r.y * r.y);
        const double x1 = -x0;
        res.emplace_back(x1 - r.x);
        res.emplace_back(x0 - r.x);
      }
    }

    /*bool overlap = false;*/
    /*if (inside(p.y, -radius, radius)) overlap = true;*/
    /*if (inside(q.y, -radius, radius)) overlap = true;*/
    /*if (inside(-radius, p.y, q.y)) overlap = true;*/
    /*if (inside(radius, p.y, q.y)) overlap = true;*/
    /**/
    /*if (true|| overlap) {*/
    const Point point_on_circle = (q - p).rot_ccw().normalize().scale(radius);
    for (const Point r : vector<Point>{point_on_circle, point_on_circle.negate()}) {
      /*if (!inside(r.y, p.y, q.y)) continue;*/

      const double yp = (r.y - p.y) / (q.y - p.y);
      const double x = p.x + (yp * (q.x - p.x));
      res.emplace_back(r.x - x);
    }
    /*}*/

    return res;
  }
};

double width(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  double a = 1e9;
  double b = -1e9;
  for (const auto p : polygon1) a = min(a, p.x);
  for (const auto p : polygon2) a = min(a, p.x);
  for (const auto p : polygon1) b = max(b, p.x);
  for (const auto p : polygon2) b = max(b, p.x);
  return b - a;
}

bool point_inside_polygon(const Point p, const vector<Segment>& polygon_edges) {
  const Segment ray{p, {1e4, 1e4 + 1e-2}};
  int intersections = 0;
  for (const Segment e : polygon_edges) intersections += e.intersect(ray);
  return intersections % 2 == 1;
}

vector<Segment> polygon_edges(const vector<Point>& polygon) {
  vector<Segment> edges;

  for (int i = 0; i < (int)polygon.size(); i++)
    edges.emplace_back(polygon[i], polygon[(i + 1) % polygon.size()]);

  return edges;
}

double polygon_distance(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  double res = 1e9;

  const vector<Segment> edges1 = polygon_edges(polygon1);
  const vector<Segment> edges2 = polygon_edges(polygon2);

  for (const Segment s : edges1) {
    if (point_inside_polygon(s.p, edges2)) return 0;
    for (const Segment r : edges2) {
      if (point_inside_polygon(r.p, edges1)) return 0;
      res = min(res, s.dist(r));
    }
  }

  return res;
}

double solve(const vector<Point>& polygon1, vector<Point> polygon2, const double L) {
  double ans = 1e9;

  vector<shared_ptr<Intersection>> obstacles;
  set<double> x_movements;

  for (const Point circle_center : polygon1)
    obstacles.emplace_back(make_shared<Circle>(circle_center, L));

  for (const Point p : polygon1)
    obstacles.emplace_back(make_shared<Segment>(Point{p.x, 2000}, Point{p.x, -2000}));

  for (const auto [p, q] : polygon_edges(polygon1)) {
    const Point dir = (p - q).normalize().rot_ccw().scale(L);
    obstacles.emplace_back(make_shared<Segment>(p + dir, q + dir));
  }

  for (const auto& obs : obstacles) {
    for (const auto [p, q] : polygon_edges(polygon2)) {
      const vector<double> xs = obs->intersections(p, q);
      copy(xs.begin(), xs.end(), inserter(x_movements, x_movements.end()));
    }
  }

  for (const double x : x_movements) {
    vector<Point> moved = polygon2;
    for (auto& p : moved) p.x += x;
    const double distance = polygon_distance(polygon1, moved);
    if (distance >= L - EPS) ans = min(ans, width(polygon1, moved));
  }

  return ans;
}

int main() {
  double L;
  while (cin >> L && L > 0) {
    int n;
    cin >> n;
    vector<Point> polygon1(n);
    for (auto& p : polygon1) cin >> p.x >> p.y;
    cin >> n;
    vector<Point> polygon2(n);
    for (auto& p : polygon2) cin >> p.x >> p.y;

    cout << fixed << setprecision(5) << solve(polygon1, polygon2, L) << endl;
  }
}
accuracy: 1
time_ms: 60
memory_kb: 3504
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-7;

bool zero(const double a) { return fabs(a) < EPS; }
bool equal(const double a, const double b) { return zero(a - b); }

struct Point {
  double x, y;
  Point rot_ccw() const { return {-y, x}; }
  double magnitude() const { return hypot(x, y); }
  Point operator+(const Point p) const { return {x + p.x, y + p.y}; }
  Point operator-(const Point p) const { return {x - p.x, y - p.y}; }
  Point scale(const double f) const { return {x * f, y * f}; }
  Point normalize() const { return scale(1 / magnitude()); }
  double dist(const Point p) const { return hypot(x - p.x, y - p.y); }
  double operator*(const Point p) const { return x * p.x + y * p.y; }
  double cross(const Point p) const { return x * p.y - y * p.x; }
  Point negate() const { return {-x, -y}; }
  bool operator==(const Point p) const { return equal(x, p.x) && equal(y, p.y); }
};

short orientation(const Point& o, const Point& a, const Point& b) {
  const double cross = (a - o).cross(b - o);
  if (fabs(cross) < EPS) return 0;
  return cross < 0 ? -1 : 1;
}

struct Intersection {
  virtual vector<double> intersections(const Point a, const Point b) const = 0;
  virtual string to_desmos() const = 0;
};

bool inside(const double v, const double a, const double b) {
  const auto [n, m] = minmax(a, b);
  return n <= v && v <= m;
}

struct Segment : Intersection {
  Point p, q;
  bool contains_except_endpoints(const Point& r) const {
    if (orientation(p, q, r) != 0) return false;
    return (q - p) * (r - p) > EPS && (p - q) * (r - q) > EPS;
  }
  Segment(const Point p, const Point q) : p(p), q(q) {}
  bool is_vertical() const { return equal(p.x, q.x); }
  double dist(const Segment s) const {
    if (intersect(s)) return 0;
    return min({dist(s.p), dist(s.q), s.dist(p), s.dist(q)});
  }
  double dist(const Point r) const {
    if ((q - p) * (r - p) <= 0) return p.dist(r);
    if ((p - q) * (r - q) <= 0) return q.dist(r);
    return fabs((q - p).cross(r - p)) / p.dist(q);
  }
  bool intersect(const Segment s) const {
    const short o1 = orientation(p, q, s.p);
    const short o2 = orientation(p, q, s.q);
    const short o3 = orientation(s.p, s.q, p);
    const short o4 = orientation(s.p, s.q, q);
    return o1 * o2 < 0 && o3 * o4 < 0;
  }
  /*bool intersect(const Segment s) const {*/
  /*  return (orientation(p, q, s.p) * orientation(p, q, s.q) < 0) &&*/
  /*         (orientation(s.p, s.q, p) * orientation(s.p, s.q, q) < 0);*/
  /*}*/
  optional<double> dist_x(const Point r) const {
    if (!inside(r.y, p.y, q.y)) return nullopt;
    if (is_vertical()) return p.x - r.x;

    const double yp = (r.y - p.y) / (q.y - p.y);
    const double x = p.x + (yp * (q.x - p.x));
    return x - r.x;
  }

  vector<double> intersections(const Point a, const Point b) const {
    vector<double> res;

    vector<optional<double>> candidates{Segment{a, b}.dist_x(p), Segment{a, b}.dist_x(q),
                                        dist_x(a), dist_x(b)};

    int i = 0;
    for (const auto x : candidates) {
      if (x.has_value()) {
        const double val = x.value();
        if (isnan(val)) continue;
        if (i < 2) {
          res.emplace_back(-val);
        } else {
          res.emplace_back(val);
        }
      }
      i++;
    }

    return res;
  }
  string to_desmos() const {
    stringstream ss;
    ss << fixed << setprecision(6) << "\\left(\\left(1-t\\right)\\cdot" << p.x
       << "+t\\cdot" << q.x << ",\\left(1-t\\right)\\cdot" << p.y << "+t\\cdot" << q.y
       << "\\right)";
    return ss.str();
  }
};

struct Circle : Intersection {
  const Point center;
  const double radius;
  Circle(const Point p, const double r) : center(p), radius(r) {}
  vector<double> intersections(Point p, Point q) const {
    p = p - center;
    q = q - center;

    vector<double> res;

    const vector<Point> ps{p, q};

    for (const Point r : ps) {
      if (inside(r.y, -radius, radius)) {
        const double x0 = sqrt(radius * radius - r.y * r.y);
        const double x1 = -x0;
        res.emplace_back(x1 - r.x);
        res.emplace_back(x0 - r.x);
      }
    }

    bool overlap = false;
    if (inside(p.y, -radius, radius)) overlap = true;
    if (inside(q.y, -radius, radius)) overlap = true;
    if (inside(-radius, p.y, q.y)) overlap = true;
    if (inside(radius, p.y, q.y)) overlap = true;

    if (overlap) {
      const Point point_on_circle = (q - p).rot_ccw().normalize().scale(radius);
      const vector<Point> ps{point_on_circle, point_on_circle.negate()};
      for (const Point r : ps) {
        if (!inside(r.y, p.y, q.y)) continue;

        const double yp = (r.y - p.y) / (q.y - p.y);
        const double x = p.x + (yp * (q.x - p.x));
        res.emplace_back(r.x - x);
      }
    }

    // todo: intersections when the segment p,q is tangent to the circle but endpoints
    // don't touch
    return res;
  }
  string to_desmos() const {
    stringstream ss;
    ss << "\\left(x-" << center.x << "\\right)^{2}+\\left(y-" << center.y
       << "\\right)^{2}=" << radius << "^{2}";
    return ss.str();
  }
};

double width(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  double a = 1e9;
  double b = -1e9;
  for (const auto& p : polygon1) {
    a = min(a, p.x);
    b = max(b, p.x);
  }
  for (const auto& p : polygon2) {
    a = min(a, p.x);
    b = max(b, p.x);
  }
  return b - a;
}
bool point_inside_polygon(const Point& p, const vector<Point>& polygon) {
  const Segment ray{p, {1e4, 1e4 + 1e-2}};

  int intersections = 0;

  for (int i = 0; i < (int)polygon.size(); i++) {
    const Segment edge{polygon[i], polygon[(i + 1) % polygon.size()]};
    intersections += edge.intersect(ray);
  }

  return intersections % 2 == 1;
}

Point vertex_at(const vector<Point>& polygon, int i) {
  int n = (int)polygon.size();
  i = (i + (n << 10)) % n;
  return polygon[i];
}

double angle(const Point& a, const Point& b) {
  const double x = atan2(a.cross(b), a * b);
  return x < 0 ? x + 2 * M_PI : x;
}
bool intersection_aux(const vector<Point>& p1, const vector<Point>& p2, int i, int j) {
  const Point &a0 = vertex_at(p1, i - 1), &a1 = vertex_at(p1, i),
              &a2 = vertex_at(p1, i + 1);
  const Point &b0 = vertex_at(p2, j - 1), &b1 = vertex_at(p2, j),
              &b2 = vertex_at(p2, j + 1);

  if (Segment{a1, a2}.intersect({b1, b2})) return true;

  if (Segment{b1, b2}.contains_except_endpoints(a1)) {
    if (orientation(b1, b2, a2) == 1) return true;
    if (orientation(b1, b2, a0) == 1) return true;
  }
  if (Segment{a1, a2}.contains_except_endpoints(b1)) {
    if (orientation(a1, a2, b2) == 1) return true;
    if (orientation(a1, a2, b0) == 1) return true;
  }

  if (a1 == b1) {
    const double th = angle(b2 - b1, b0 - b1);
    double th2 = angle(b2 - b1, a0 - b1);
    if (th2 > EPS && th2 < th - EPS) return true;
    th2 = angle(b2 - b1, a2 - b1);
    if (th2 > EPS && th2 < th - EPS) return true;
  }

  return false;
}

bool intersection(const vector<Point>& p1, const vector<Point>& p2) {
  const int n = p1.size();
  const int m = p2.size();
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (intersection_aux(p1, p2, i, j)) return true;
    }
  }
  return false;
}

string polygon_to_str(const vector<Point>& polygon) {
  stringstream ss;
  ss << fixed << setprecision(6);
  ss << "polygon(";
  for (int i = 0; i < (int)polygon.size(); i++) {
    if (i > 0) ss << ", ";
    ss << "(" << polygon[i].x << ", " << polygon[i].y << ")";
  }
  ss << ")";
  return ss.str();
}

double polygon_distance(const vector<Point>& polygon1, const vector<Point>& polygon2) {
  /*if (intersection(polygon1, polygon2)) return 0;*/
  double res = 1e9;

  vector<Segment> edges1, edges2;
  int n = polygon1.size();
  for (int i = n - 1, j = 0; j < n; i = j++) {
    const Point p = polygon1[i];
    if (point_inside_polygon(p, polygon2)) return 0;
    const Point q = polygon1[j];
    edges1.emplace_back(p, q);
  }

  n = polygon2.size();
  for (int i = n - 1, j = 0; j < n; i = j++) {
    const Point p = polygon2[i];
    if (point_inside_polygon(p, polygon1)) return 0;
    const Point q = polygon2[j];
    edges2.emplace_back(p, q);
  }

  for (const Segment s : edges1) {
    for (const Segment r : edges2) {
      res = min(res, s.dist(r));
    }
  }

  return res;
}

double solve(const vector<Point>& polygon1, vector<Point> polygon2, const double L,
             const int test_case) {
  double ans = 1e9;
  const int dbg = -263;
  for (auto& p : polygon2) p.x -= 2000;

  if (test_case == dbg) {
    cerr << fixed << setprecision(3) << "L: " << L << endl;
    cerr << "original polygons:" << endl;
    cerr << polygon_to_str(polygon1) << endl;
    cerr << polygon_to_str(polygon2) << endl << endl;
  }

  vector<shared_ptr<Intersection>> obstacles;
  set<double> x_movements;

  for (const Point circle_center : polygon1) {
    obstacles.emplace_back(make_shared<Circle>(circle_center, L));
  }

  for (const Point p : polygon1) {
    obstacles.emplace_back(make_shared<Segment>(Point{p.x, 2000}, Point{p.x, -2000}));
  }

  const int n = polygon1.size();
  for (int i = n - 1, j = 0; j < n; i = j++) {
    const Point p = polygon1[i];
    const Point q = polygon1[j];
    const Point dir = (p - q).normalize().rot_ccw().scale(L);
    obstacles.emplace_back(make_shared<Segment>(p + dir, q + dir));
  }

  for (const auto& obs : obstacles) {
    const int n = polygon2.size();
    for (int i = n - 1, j = 0; j < n; i = j++) {
      const Point p = polygon2[i];
      const Point q = polygon2[j];
      for (const double x : obs->intersections(p, q)) {
        assert(!isnan(x));
        x_movements.emplace(x);
      }
    }
  }

  /*cerr << "movements: " << x_movements.size() << endl;*/
  if (x_movements.empty()) {
    const double w1 = width(polygon1, {});
    const double w2 = width(polygon2, {});
    /*cerr << endl << "------------" << endl << endl;*/
    return max(w1, w2);
  }

  for (const double x_movement : x_movements) {
    vector<Point> moved = polygon2;
    for (auto& p : moved) p.x += x_movement;
    if (test_case == dbg) {
      cerr << polygon_to_str(moved) << endl;
    }
    const double distance = polygon_distance(polygon1, moved);
    const double w = width(polygon1, moved);
    if (distance >= L - EPS) {  // TODO: this is fucked up lol
      ans = min(ans, w);
    }
    if (test_case == dbg) {
      cerr << fixed << setprecision(6) << "movement: " << x_movement << endl;
      cerr << fixed << setprecision(6) << "width: " << w << endl;
      cerr << fixed << setprecision(6) << "dist: " << distance << endl;
      cerr << fixed << setprecision(6) << "curr best: " << ans << endl;
      cerr << endl;
    }
  }

  /*if (test_case == dbg) {*/
  /*  cerr << "OBSTACLES" << endl;*/
  /*  for (const auto& obs : obstacles) {*/
  /*    cerr << obs->to_desmos() << endl;*/
  /*  }*/
  /*  cerr << endl;*/
  /*}*/

  /*cerr << endl << "------------" << endl << endl;*/
  return ans;
}

int main() {
  double L;
  int t = 1;
  while (cin >> L && L > 0) {
    int n;
    cin >> n;
    vector<Point> polygon1(n);
    for (auto& p : polygon1) cin >> p.x >> p.y;
    cin >> n;
    vector<Point> polygon2(n);
    for (auto& p : polygon2) cin >> p.x >> p.y;

    const double val1 = solve(polygon1, polygon2, L, t);
    const double val2 = solve(polygon2, polygon1, L, -1);

    cout << fixed << setprecision(5) << min(val1, val2) << endl;
    t++;
  }
}
accuracy: 1
time_ms: 50
memory_kb: 3624
final_rank: 8

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 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 intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
double distanceSP(const L &s, const P &p) {
    if(dot(s[1]-s[0], p-s[0]) < EPS) return abs(p-s[0]);
    if(dot(s[0]-s[1], p-s[1]) < EPS) return abs(p-s[1]);
    return distanceLP(s, p);
}
double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

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 in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = -ret;
    }
    return ret;
}

double distanceGG(VP &a, VP &b){
    int n = a.size();
    int m = b.size();
    if(in_poly(a[0], b) > 0 || in_poly(b[0], a) > 0){
        return 0;
    }
    double ret = INF;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            ret = min(ret, distanceSS(L(a[i], a[(i+1)%n]), L(b[j], b[(j+1)%m])));
        }
    }
    return ret;
}

double leftend(VP &poly){
    double ret = INF;
    for(P p: poly){
        ret = min(ret, p.X);
    }
    return ret;
}
double rightend(VP &poly){
    double ret = -INF;
    for(P p: poly){
        ret = max(ret, p.X);
    }
    return ret;
}
VP slide(VP poly, double d){
    for(P &p: poly){
        p += P(d, 0);
    }
    return poly;
}
L slide(L l, double d){
    return L(l[0] +P(d, 0), l[1] +P(d, 0));
}
//aとbの距離を最も近づけるためには, bをx方向にretスライドすればよい
double closest_slide(L a, L b){
    if(a[0].Y > a[1].Y) swap(a[0], a[1]);
    if(b[0].Y > b[1].Y) swap(b[0], b[1]);
    //Yの範囲に被りがある
    for(int d=0; d<2; d++){
        for(int i=0; i<2; i++){
            if(b[0].Y +EPS < a[i].Y && a[i].Y +EPS < b[1].Y){
                L hori(a[i], a[i] +P(1, 0));
                P cp = crosspointLL(hori, b);
                double diff = a[i].X -cp.X;
                return (d == 0)? diff : -diff;
            }
        }
        swap(a, b);
    }
    //ない
    if(a[1].Y < b[0].Y +EPS){
        return a[1].X -b[0].X;
    }else{
        return a[0].X -b[1].X;
    }
}

int main(){
    cout << fixed << setprecision(5);
    while(1){
        double d;
        cin >> d;
        if(d == 0) break;

        vector<VP> poly(2);
        for(int d=0; d<2; d++){
            int n;
            cin >> n;
            poly[d].resize(n);
            for(int i=0; i<n; i++){
                double x,y;
                cin >> x >> y;
                poly[d][i] = P(x, y);
            }
        }
        double diff = leftend(poly[1]) -leftend(poly[0]);
        poly[1] = slide(poly[1], -diff);
        if(distanceGG(poly[0], poly[1]) +EPS > d){
            double left = min(leftend(poly[0]), leftend(poly[1]));
            double right = max(rightend(poly[0]), rightend(poly[1]));
            cout << right -left << endl;
            continue;
        }

        int n = poly[0].size();
        int m = poly[1].size();
        vector<double> cand;
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                L edge[2];
                edge[0] = L(poly[0][i], poly[0][(i+1)%n]);
                edge[1] = L(poly[1][j], poly[1][(j+1)%m]);
                double csd = closest_slide(edge[0], edge[1]);
                edge[1] = slide(edge[1], csd);
                //NG範囲をもたない
                if(distanceSS(edge[0], edge[1]) +EPS > d){
                    continue;
                }
                //NG範囲をにぶたん
                for(int s=0; s<2; s++){
                    double lb=0, ub=1e4;
                    for(int rep=0; rep<50; rep++){
                        double mid = (lb +ub) /2;
                        L tmp = (s==0)? slide(edge[1], mid) : slide(edge[1], -mid);
                        if(distanceSS(edge[0], tmp) > d){
                            ub = mid;
                        }else{
                            lb = mid;
                        }
                    }
                    if(s == 0){
                        cand.push_back(csd +lb);
                    }else{
                        cand.push_back(csd -lb);
                    }
                }
            }
        }

        double ans = INF;
        for(double dist: cand){
            VP tmp = slide(poly[1], dist);
            if(distanceGG(poly[0], tmp) +EPS > d){
                double left = min(leftend(poly[0]), leftend(tmp));
                double right = max(rightend(poly[0]), rightend(tmp));
                ans = min(ans, right -left);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 3260
final_rank: 4

code_snippet: /*
 *   Created By phyxnj@uestc
 *   Last Compiler:
 *   Sun, 29 Jul 2012 02:07:44 +0800
 */
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
#include <vector>
#include <utility>
#include <string>
#include <map>
#include <iostream>
using namespace std;
#define eps 1e-7
#define pw(x) ((x)*(x))
typedef long long LL;
struct P
{
    double x,y;
    P () {}
    P (double x,double y) : x(x),y(y) {}
    P operator - (const P & b)
    {
        return P (x-b.x,y-b.y);
    }
    double operator * (const P & b)
    {
        return x*b.y-y*b.x;
    }
    double operator & (const P & b)
    {
        return x*b.x+y*b.y;
    }
    double dorm()
    {
        return sqrt(pw(x)+pw(y));
    }
}p[300],s[300],tp[300];
int sgn(double x)
{
    return x<-eps?-1:x>eps;
}
double cal(P a,P b,P c) // 隶。邂幼蛻ーab逧?怙蟆剰キ晉ヲサ
{
    int t1=sgn((c-a)&(b-a));
    int t2=sgn((c-b)&(a-b));
    if(t1>=0&&t2>=0) return fabs((a-c)*(a-b))/(a-b).dorm();
    return min((c-a).dorm(),(c-b).dorm());
}
double maybe[10000]; 
int cnt,flag;
double L;
int n,m;
void run(P a,P b,P c) // 隶。邂苓ヲ∽スソ蠕幼荳斬b逧?怙蟆剰キ晉ヲサ荳コL隕∽スソc遘サ蜉ィ逧?キ晉ヲサ
{
    double l=-20000,h=20000,mid1,mid2;
    for(int i=0;i<50;i++){
        mid1=(2*l+h)/3;
        mid2=(2*h+l)/3;
        double t1=cal(a,b,P(mid1,c.y));
        double t2=cal(a,b,P(mid2,c.y));
        if(sgn(t1-t2)>=0) l=mid1;
        else h=mid2;
    }
    double mid;
    l=-20000;h=mid1;
    for(int i=0;i<50;i++){
        mid=(l+h)/2;
        double t1=cal(a,b,P(mid,c.y));
        if(sgn(t1-L)>=0) l=mid;
        else h=mid;
    }
    double delta=mid-c.x;
    if(flag) delta=-delta;
    maybe[cnt++]=delta;
    l=mid1,h=20000;
    for(int i=0;i<50;i++){
        mid=(l+h)/2;
        double t1=cal(a,b,P(mid,c.y));
        if(sgn(t1-L)>=0) h=mid;
        else l=mid;
    }
    delta=mid-c.x;
    if(flag) delta=-delta;
    maybe[cnt++]=delta;
}
void creat()
{
    cnt=0;
    s[m]=s[0],p[n]=p[0];
    flag=1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            run(s[j],s[j+1],p[i]);
        }
    }
    flag=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            run(p[j],p[j+1],s[i]);
        }
    }
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++) {
            maybe[cnt++]=p[j].x-s[i].x;
        }
    }
}
int in(P a,P pt[],int n)
{
    int cnt=0;
    pt[n]=pt[0];
    for(int i=0;i<n;i++){
        P x=pt[i],y=pt[i+1];
        if(sgn(x.y-y.y)>0) swap(x,y);
        if(sgn(x.y-a.y)>=0||sgn(y.y-a.y)<0) continue;
        double t=(x-a)*(y-a);
        if(sgn(t)>0) cnt++;
    }
    return cnt&1;
}
double solve()
{
    double ans=1e10;
    for(int i=0;i<cnt;i++){
        double x=maybe[i];
//        printf("%f\n",x);
        for(int j=0;j<m;j++){
            tp[j].x=s[j].x+x;
            tp[j].y=s[j].y;
        }
        tp[m]=tp[0];
        int flag=0;
        for(int j=0;j<n;j++){
            for(int k=0;k<m;k++){
                int t1=sgn((p[j]-tp[k])*(tp[k+1]-tp[k]))*sgn((p[j+1]-tp[k])*(tp[k+1]-tp[k]));
                int t2=sgn((tp[k]-p[j])*(p[j+1]-p[j]))*sgn((tp[k+1]-p[j])*(p[j+1]-p[j]));
                if(t1<0&&t2<0) {
                    flag=1;
                    break;
                }
                double dis=min(min(cal(p[j],p[j+1],tp[k]),cal(p[j],p[j+1],tp[k+1])),min(cal(tp[k],tp[k+1],p[j]),cal(tp[k],tp[k+1],p[j+1])));
                if(dis-L<-1e-6) {
                    flag=1;
                    break;
                }
            }
        }
        if(flag) continue;
        flag=in(tp[0],p,n)||in(p[0],tp,m);
        if(flag) continue;
        double minx=1e10,maxx=-1e10;
        for(int j=0;j<m;j++){
            minx=min(minx,tp[j].x);
            maxx=max(maxx,tp[j].x);
        }
        for(int j=0;j<n;j++){
            minx=min(minx,p[j].x);
            maxx=max(maxx,p[j].x);
        }
//        printf("%f %f ************\n",maxx,minx);
        ans=min(ans,maxx-minx);
    }
    return ans;
}
int main()
{   
    P a,b,c;
    while(scanf("%lf",&L)&&sgn(L)){
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        scanf("%d",&m);
        for(int i=0;i<m;i++) scanf("%lf%lf",&s[i].x,&s[i].y);
        creat();
        printf("%f\n",solve());
    }
    return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 964
final_rank: 1

code_snippet: #include <stdio.h>
#include <math.h>
#include <iostream>
#include <complex>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(int)(n); i++)
#define INF (1e100)
#define EPS (1e-5)
typedef complex<double> P;
inline double sq(double a) { return a*a; }

inline double cross(const P& a, const P& b) { return imag(conj(a)*b); }
inline double dot(const P& a, const P& b) { return real(conj(a)*b); }
inline P unit(const P& p) { return 1/abs(p)*p; }
int ccw(const P& a, P b, P c) {
    b -= a; c -= a;
    if(cross(b, c) > 0) return 1;
    if(cross(b, c) < 0) return -1;
    if(dot(b, c) < 0) return 2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}

inline double intersectSP(const P& s0, const P& s1, const P& p) {
    return abs(s0-p)+abs(s1-p)-abs(s1-s0) < EPS;
}

P projection(const P& l0, const P& l1, const P& p) {
    const double t = dot(p-l0, l1-l0) / norm(l1-l0);
    return l0 + t*(l1-l0);
}

double distanceSP(const P& s0, const P& s1, const P& p) {
    const P r = projection(s0, s1, p);
    if(intersectSP(s0, s1, r)) return abs(r-p);
    return min(abs(s0-p), abs(s1-p));
}

bool intersectSS(const P & s0, const P& s1, const P& t0, const P& t1) {
    return ccw(s0, s1, t0) * ccw(s0, s1, t1) <= 0
        && ccw(t0, t1, s0) * ccw(t0, t1, s1) <= 0;
}

P crosspoint(const P& l0, const P& l1, const P& m0, const P& m1) {
    const double A = cross(l1-l0, m1-m0);
    const double B = cross(l1-l0, l1-m0);
    if(abs(A)<EPS && abs(B)<EPS) return m0;
    // if(abs(A)<EPS) assert(false);
    return m0+B/A*(m1-m0);
}

double distanceSS(const P& s0, const P& s1, const P& t0, const P& t1) {
    if(intersectSS(s0, s1, t0, t1)) return 0;
    return min(min(distanceSP(s0, s1, t0), distanceSP(s0, s1, t1)),
               min(distanceSP(t0, t1, s0), distanceSP(t0, t1, s1)));
}

vector<P> crosspointsCL(const P& p, double r, const P& l0, const P& l1) {
    vector<P> v;
    const P cp(crosspoint(p, p+(l1-l0)*P(0, 1), l0, l1));
    if(abs(cp-p) < r+EPS) {
        const double a = sqrt(sq(r)-norm(p-cp));
        const P dir(a*unit(l1-l0));
        v.push_back(cp+dir); v.push_back(cp-dir);
    }
    return v;
}

bool contains(const vector<P>& ps, const P& p) {
    bool in = false;
    rep(i, ps.size()) {
        const int j = (i+1)%ps.size();
        P a(ps[i]-p), b(ps[j]-p);
        if(imag(a) > imag(b)) swap(a, b);
        if(imag(a) <= 0 && 0 < imag(b) && cross(a, b) < 0) in = !in;
        if(cross(a, b)==0 && dot(a, b) <= 0) return true; // on edge
    }
    return in;
}

double L;
int n[2], xo[2][20], yo[2][20];
P po[2][20];

bool check(double dx) {
    vector<P> pm[2];
    rep(i, n[0]) pm[0].push_back(po[0][i]);
    rep(i, n[1]) pm[1].push_back(po[1][i] + P(dx, 0));
    rep(k, 2) rep(i, n[k]) if(contains(pm[1-k], pm[k][i])) return false;
    rep(i, n[0]) rep(j, n[1]) if(abs(pm[1][j]-pm[0][i])<L-EPS) return false;
    rep(k, 2) rep(i, n[k]) {
        const int j = (i+1)%n[k];
        rep(a, n[1-k]) {
            if(distanceSP(pm[k][i], pm[k][j], pm[1-k][a])<L-EPS) return false;
        }
    }
    rep(i, n[0]) rep(j, n[1]) {
        const int it = (i+1)%n[0];
        const int jt = (j+1)%n[1];
        if(distanceSS(pm[0][i], pm[0][it], pm[1][j], pm[1][jt])<L-EPS) {
            return false;
        }
    }
    return true;
}

int main() {
    for(;;) {
        scanf("%lf", &L);
        if(fabs(L)<EPS) return 0;
        rep(k, 2) {
            scanf("%d", n+k);
            rep(i, n[k]) scanf("%d%d", xo[k]+i, yo[k]+i);
            rep(i, n[k]) po[k][i] = P(xo[k][i], yo[k][i]);
        }
        vector<double> cands;
        rep(i, n[0]) rep(j, n[1]) cands.push_back(xo[0][i]-xo[1][j]);
        rep(i, n[0]) rep(j, n[1]) {
            const double y = yo[1][j];
            vector<P> ps(crosspointsCL(po[0][i], L, P(-1000, y), P(1000, y)));
            rep(k, ps.size()) cands.push_back(ps[k].real()-xo[1][j]);
        }
        rep(k, 2) rep(i, n[k]) {
            const int j = (i+1)%n[k];
            rep(a, n[1-k]) {
                const P dir(L*unit(po[k][j]-po[k][i])*P(0, 1));
                vector<P> ps;
                ps.push_back(po[1-k][a]+dir);
                ps.push_back(po[1-k][a]-dir);
                rep(b, ps.size()) {
                    const double y = yo[k][i];
                    const P cp(crosspoint(ps[b], ps[b]+(po[k][j]-po[k][i]),
                                P(-1000, y), P(1000, y)));
                    if(k) cands.push_back(cp.real()-xo[k][i]);
                    else cands.push_back(xo[k][i]-cp.real());
                }
            }
        }
        sort(cands.begin(), cands.end());
        cands.erase(unique(cands.begin(), cands.end()), cands.end());
        double ans = INF;
        rep(k, cands.size()) if(check(cands[k])) {
            double xmin = INF, xmax = -INF;
            rep(i, n[0]) {
                xmin = min(xmin, (double)xo[0][i]);
                xmax = max(xmax, (double)xo[0][i]);
            }
            rep(i, n[1]) {
                xmin = min(xmin, (double)xo[1][i]+cands[k]);
                xmax = max(xmax, (double)xo[1][i]+cands[k]);
            }
            ans = min(ans, xmax-xmin);
        }
        printf("%.12f\n", ans);
    }
}
accuracy: 1
time_ms: 1040
memory_kb: 1016
final_rank: 2

code_snippet: #include <stdio.h>
#include <math.h>
#include <iostream>
#include <complex>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(int)(n); i++)
#define INF (1e100)
#define EPS (1e-5)
typedef complex<double> P;
inline double sq(double a) { return a*a; }

inline double cross(const P& a, const P& b) { return imag(conj(a)*b); }
inline double dot(const P& a, const P& b) { return real(conj(a)*b); }
inline P unit(const P& p) { return 1/abs(p)*p; }
int ccw(const P& a, P b, P c) {
    b -= a; c -= a;
    if(cross(b, c) > 0) return 1;
    if(cross(b, c) < 0) return -1;
    if(dot(b, c) < 0) return 2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}

inline double intersectSP(const P& s0, const P& s1, const P& p) {
    return abs(s0-p)+abs(s1-p)-abs(s1-s0) < EPS;
}

P projection(const P& l0, const P& l1, const P& p) {
    const double t = dot(p-l0, l0-l1) / norm(l0-l1);
    return l0 + t*(l0-l1);
}

double distanceSP(const P& s0, const P& s1, const P& p) {
    const P r = projection(s0, s1, p);
    if(intersectSP(s0, s1, r)) return abs(r-p);
    return min(abs(s0-p), abs(s1-p));
}

bool intersectSS(const P & s0, const P& s1, const P& t0, const P& t1) {
    return ccw(s0, s1, t0)*ccw(s0, s1, t1) <= 0
        && ccw(t0, t1, s0)*ccw(t0, t1, s1) <= 0;
}

P crosspoint(const P& l0, const P& l1, const P& m0, const P& m1) {
    const double A = cross(l1-l0, m1-m0);
    const double B = cross(l1-l0, l1-m0);
    if(abs(A)<EPS && abs(B)<EPS) return m0;
    return m0+B/A*(m1-m0);
}

double distanceSS(const P& s0, const P& s1, const P& t0, const P& t1) {
    if(intersectSS(s0, s1, t0, t1)) return 0;
    return min(min(distanceSP(s0, s1, t0), distanceSP(s0, s1, t1)),
               min(distanceSP(t0, t1, s0), distanceSP(t0, t1, s1)));
}

vector<P> crosspointsCL(const P& p, double r, const P& l0, const P& l1) {
    vector<P> v;
    const P cp(crosspoint(p, p+(l1-l0)*P(0, 1), l0, l1));
    if(abs(cp-p)<EPS) {
        const P dir(r*unit(l1-l0));
        v.push_back(p+dir); v.push_back(p-dir);
    }
    else if(abs(cp-p)<r+EPS) {
        const double a = sqrt(sq(r)-norm(p-cp));
        const P dir(a*unit(cp-p)*P(0, 1));
        v.push_back(cp+dir); v.push_back(cp-dir);
    }
    return v;
}

bool contains(const vector<P>& ps, const P& p) {
    bool in = false;
    rep(i, ps.size()) {
        P a(ps[i]-p), b(ps[(i+1)%ps.size()]-p);
        if(imag(a) > imag(b)) swap(a, b);
        if(imag(a) <= 0 && 0 < imag(b) && cross(a, b) < 0) in = !in;
        if(cross(a, b)==0 && dot(a, b) <= 0) return true; // 'on'
    }
    return in;
}

double L;
int n[2], xo[2][20], yo[2][20];
P po[2][20];

bool check(double dx) {
    vector<P> pm[2];
    rep(i, n[0]) pm[0].push_back(po[0][i]);
    rep(i, n[1]) pm[1].push_back(po[1][i] + P(dx, 0));
    rep(k, 2) rep(i, n[k]) if(contains(pm[1-k], pm[k][i])) return false;
    rep(i, n[0]) rep(j, n[1]) if(abs(pm[1][j]-pm[0][i])<L-EPS) return false;
    rep(k, 2) rep(i, n[k]) {
        const int j = (i+1)%n[k];
        rep(a, n[1-k]) {
            if(distanceSP(pm[k][i], pm[k][j], pm[1-k][a])<L-EPS) return false;
        }
    }
    rep(i, n[0]) rep(j, n[1]) {
        const int it = (i+1)%n[0];
        const int jt = (j+1)%n[1];
        if(distanceSS(pm[0][i], pm[0][it], pm[1][j], pm[1][jt])<L-EPS) {
            return false;
        }
    }
    return true;
}

int main() {
    for(;;) {
        scanf("%lf", &L);
        if(fabs(L)<EPS) return 0;
        rep(k, 2) {
            scanf("%d", n+k);
            rep(i, n[k]) scanf("%d%d", xo[k]+i, yo[k]+i);
            rep(i, n[k]) po[k][i] = P(xo[k][i], yo[k][i]);
        }
        vector<double> cands;
        rep(i, n[0]) rep(j, n[1]) cands.push_back(xo[0][i]-xo[1][j]);
        rep(i, n[0]) rep(j, n[1]) {
            const double y = yo[1][j];
            vector<P> ps(crosspointsCL(po[0][i], L, P(-1000, y), P(1000, y)));
            rep(k, ps.size()) cands.push_back(ps[k].real()-xo[1][j]);
        }
        rep(k, 2) rep(i, n[k]) {
            const int j = (i+1)%n[k];
            rep(a, n[1-k]) {
                const P dir(L*unit(po[k][j]-po[k][i])*P(0, 1));
                vector<P> ps;
                ps.push_back(po[1-k][a]+dir);
                ps.push_back(po[1-k][a]-dir);
                rep(b, ps.size()) {
                    const double y = yo[k][i];
                    const P cp(crosspoint(ps[b], ps[b]+(po[k][j]-po[k][i]),
                                P(-1000, y), P(1000, y)));
                    if(k) cands.push_back(cp.real()-xo[k][i]);
                    else cands.push_back(xo[k][i]-cp.real());
                }
            }
        }
        sort(cands.begin(), cands.end());
        cands.erase(unique(cands.begin(), cands.end()), cands.end());
        double ans = INF;
        rep(k, cands.size()) if(check(cands[k])) {
            double xmin = INF, xmax = -INF;
            rep(i, n[0]) {
                xmin = min(xmin, (double)xo[0][i]);
                xmax = max(xmax, (double)xo[0][i]);
            }
            rep(i, n[1]) {
                xmin = min(xmin, (double)xo[1][i]+cands[k]);
                xmax = max(xmax, (double)xo[1][i]+cands[k]);
            }
            ans = min(ans, xmax-xmin);
        }
        printf("%.12f\n", ans);
    }
}
accuracy: 1
time_ms: 1050
memory_kb: 1020
final_rank: 3

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

typedef complex<double>     P;
typedef pair<P,P>           Line;
typedef pair<double,double> pdd;

const double eps = 1e-10;
const double INF = 10000;

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

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

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

double distance_ls_p(P &a,P &b,P &c){
  if (dot(b-a,c-a) < eps)return abs(c-a);
  if (dot(a-b,c-b) < eps)return abs(c-b);
  return abs(cross(b-a,c-a))/abs(b-a);
}

#define D distance_ls_p
double distance_ss_p(P a,P b,P c,P d){
  return min(  min( D(a,b,c),D(a,b,d)),min(D(c,d,a),D(c,d,b)));
}

bool is_intersected_ls(P a1,P a2,P b1,P b2){
  if ( isp(a1,a2,b1))return true;
  if ( isp(a1,a2,b2))return true;
  if ( isp(b1,b2,a1))return true;
  if ( isp(b1,b2,a2))return true;
  if (  ( cross(a2-a1,b1-a1) * cross(a2-a1,b2-a1)<-eps ) && 
	( cross(b2-b1,a1-b1)*cross(b2-b1,a2-b1)<-eps))return true;
  else return false;
}


double tri_search(double left,double right,Line &a,P &b){
  double mleft,mright;
  while(left < right){
    mleft =(right  +2*left)/3;
    mright=(right*2+  left)/3;
    P tb(b.real(),b.imag());
    tb.real()=b.real()+mleft;
    double ldist=distance_ls_p(a.first,a.second,tb);
    tb.real()=b.real()+mright;
    double rdist=distance_ls_p(a.first,a.second,tb);
    if (rdist > ldist){
      right=mright-eps;
    }else {
      left=mleft+eps;
    }    
  }  
  return (right+left)/2;
}

double bsearch(double left,double right,Line &a,P &b,double L){
  double mid=0;
  rep(i,250){
    mid = (left+right)/2;
    P tb(b.real(),b.imag());
    tb.real()=b.real()+mid;
    double dist=distance_ls_p(a.first,a.second,tb);
    if (dist <L){
      left=mid+eps;
    }else {
      right=mid-eps;
    }
  }
  return mid;
}

pdd find_L(Line &a,P &b,double L){
  if (a.first.imag() == a.second.imag()){
    double l = bsearch(min(a.first.real(),a.second.real()),-INF,a,b,L);
    double r = bsearch(max(a.first.real(),a.second.real()), INF,a,b,L);    
    return mp(l,r);
  }else {
    double mid = tri_search(-INF,INF,a,b);
    double l=bsearch(mid,-INF,a,b,L);
    double r=bsearch(mid,INF,a,b,L);
    return mp(l,r);
  }
}

pdd get_L(Line &a,P &b,double L){
  pdd Lpoint=find_L(a,b,L);
  return Lpoint;
}

void find_Ldif(Line a,Line b,double L,vector<double> &ret,vector<double>&ret2){
  pdd cand[4];
  cand[0]=get_L(a,b.first,L);
  cand[1]=get_L(a,b.second,L);
  cand[2]=get_L(b,a.first,L);
  cand[3]=get_L(b,a.second,L);
  
  rep(i,2){
    if (cand[i].first < -INF+1 || cand[i].first > INF-1);
    else ret.pb(cand[i].first);
    if (cand[i].second < -INF+1 || cand[i].second > INF-1);
    else ret.pb(cand[i].second);
  }

  REP(i,2,4){
    if (cand[i].first < -INF+1 || cand[i].first > INF-1);
    else ret2.pb(cand[i].first);
    if (cand[i].second < -INF+1 || cand[i].second > INF-1);
    else ret2.pb(cand[i].second);
  }
}

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;
}

bool isok(vector<P> &va,vector<P> &vb,double L){
  rep(i,va.size()){
    rep(j,vb.size()){
      double tmp = distance_ss_p(va[i],va[(i+1)%va.size()],vb[j],vb[(j+1)%vb.size()]);
      if (tmp+eps < L){
	return false;
      }
    }
  }

  rep(i,vb.size()){
    if (is_in(va,vb[i]))return false;
  }

  rep(i,va.size()){
    if (is_in(vb,va[i]))return false;
  }

  rep(i,va.size()){
    rep(j,vb.size()){
      if (is_intersected_ls(va[i],va[(i+1)%va.size()],vb[j],vb[(j+1)%vb.size()]))return false;
    }
  }

  return true;
}

double compute_width(vector<P> &va,vector<P> &vb){
  double maxi=-INF,mini=INF;
  rep(i,va.size()){
    maxi=max(va[i].real(),maxi);
    mini=min(va[i].real(),mini);
  }
  rep(i,vb.size()){
    maxi=max(vb[i].real(),maxi);
    mini=min(vb[i].real(),mini);
  }
  return maxi-mini;
}

double solve(vector<P> &va,vector<P> vb,vector<double> &cand,double L){
  double ans =1e10;

  rep(i,cand.size()){
    rep(j,vb.size())vb[j].real()+=cand[i];
    if (isok(va,vb,L) ){
      ans=min(ans,compute_width(va,vb));
    }
    rep(j,vb.size())vb[j].real()-=cand[i];
  }
  return ans;
}


main(){
  double L;
  while(cin>>L && L){
    vector<P> va,vb;
    P a;
    int n;
    cin>>n;
    rep(i,n){
      cin>>a.real()>>a.imag();
      va.pb(a);
    }
    
    int m;
    cin>>m;
    rep(i,m){
      cin>>a.real()>>a.imag();
      vb.pb(a);
    }

    vector<double> cand_a;
    vector<double> cand_b;
    rep(i,va.size()){
      rep(j,vb.size()){
	find_Ldif(mp(va[i],va[(i+1)%va.size()]),mp(vb[j],vb[(j+1)%vb.size()]),L,cand_a,cand_b);
      }
    }
    
    double ans =min(solve(va,vb,cand_a,L),solve(vb,va,cand_b,L));
    printf("%.8lf\n",ans);
  }
  
  return false;
}
accuracy: 1
time_ms: 2060
memory_kb: 1024
final_rank: 10

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

typedef complex<double>     P;
typedef pair<P,P>           Line;
typedef pair<double,double> pdd;

const double eps = 1e-10;
const double INF = 10000;

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

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

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

double distance_ls_p(P &a,P &b,P &c){
  if (dot(b-a,c-a) < eps)return abs(c-a);
  if (dot(a-b,c-b) < eps)return abs(c-b);
  return abs(cross(b-a,c-a))/abs(b-a);
}

#define D distance_ls_p
double distance_ss_p(P a,P b,P c,P d){
  return min(  min( D(a,b,c),D(a,b,d)),min(D(c,d,a),D(c,d,b)));
}

bool is_intersected_ls(P a1,P a2,P b1,P b2){
  if ( isp(a1,a2,b1))return true;
  if ( isp(a1,a2,b2))return true;
  if ( isp(b1,b2,a1))return true;
  if ( isp(b1,b2,a2))return true;
  if (  ( cross(a2-a1,b1-a1) * cross(a2-a1,b2-a1)<-eps ) && 
	( cross(b2-b1,a1-b1)*cross(b2-b1,a2-b1)<-eps))return true;
  else return false;
}


double tri_search(double left,double right,Line &a,P &b){
  double mleft,mright;
  while(left < right){
    mleft =(right  +2*left)/3;
    mright=(right*2+  left)/3;
    P tb=b;
    tb.real()=b.real()+mleft;
    double ldist=distance_ls_p(a.first,a.second,tb);
    tb.real()=b.real()+mright;
    double rdist=distance_ls_p(a.first,a.second,tb);
    if (rdist > ldist){
      right=mright-eps;
    }else {
      left=mleft+eps;
    }    
  }  
  return (right+left)/2;
}

double bsearch(double left,double right,Line &a,P &b,double L){
  double mid=0;
  rep(i,250){
    mid = (left+right)/2;
    P tb=b;
    tb.real()=b.real()+mid;
    double dist=distance_ls_p(a.first,a.second,tb);
    if (dist <L){
      left=mid+eps;
    }else {
      right=mid-eps;
    }
  }
  return mid;
}

pdd find_L(Line &a,P &b,double L){
  if (a.first.imag() == a.second.imag()){
    double l = bsearch(min(a.first.real(),a.second.real()),-INF,a,b,L);
    double r = bsearch(max(a.first.real(),a.second.real()), INF,a,b,L);    
    return mp(l,r);
  }else {
    double mid = tri_search(-INF,INF,a,b);
    double l=bsearch(mid,-INF,a,b,L);
    double r=bsearch(mid,INF,a,b,L);
    return mp(l,r);
  }
}

pdd get_L(Line &a,P &b,double L){
  pdd Lpoint=find_L(a,b,L);
  
  P tb=b;
  tb.real()=b.real()+Lpoint.first;
  tb.real()=b.real()+Lpoint.second;
  return Lpoint;
}

void find_Ldif(Line a,Line b,double L,vector<double> &ret,vector<double>&ret2){
  pdd cand[4];
  cand[0]=get_L(a,b.first,L);
  cand[1]=get_L(a,b.second,L);
  cand[2]=get_L(b,a.first,L);
  cand[3]=get_L(b,a.second,L);
  
  rep(i,2){
    if (cand[i].first < -INF+1 || cand[i].first > INF-1);
    else ret.pb(cand[i].first);
    if (cand[i].second < -INF+1 || cand[i].second > INF-1);
    else ret.pb(cand[i].second);
  }

  REP(i,2,4){
    if (cand[i].first < -INF+1 || cand[i].first > INF-1);
    else ret2.pb(cand[i].first);
    if (cand[i].second < -INF+1 || cand[i].second > INF-1);
    else ret2.pb(cand[i].second);
  }
}

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;
}

bool isok(vector<P> &va,vector<P> &vb,double L){
  rep(i,va.size()){
    rep(j,vb.size()){
      double tmp = distance_ss_p(va[i],va[(i+1)%va.size()],vb[j],vb[(j+1)%vb.size()]);
      if (tmp+eps < L){
	return false;
      }
    }
  }

  rep(i,vb.size()){
    if (is_in(va,vb[i]))return false;
  }

  rep(i,va.size()){
    if (is_in(vb,va[i]))return false;
  }

  rep(i,va.size()){
    rep(j,vb.size()){
      if (is_intersected_ls(va[i],va[(i+1)%va.size()],vb[j],vb[(j+1)%vb.size()]))return false;
    }
  }

  return true;
}

double compute_width(vector<P> &va,vector<P> &vb){
  double maxi=-INF,mini=INF;
  rep(i,va.size()){
    maxi=max(va[i].real(),maxi);
    mini=min(va[i].real(),mini);
  }
  rep(i,vb.size()){
    maxi=max(vb[i].real(),maxi);
    mini=min(vb[i].real(),mini);
  }
  return maxi-mini;
}

double solve(vector<P> &va,vector<P> vb,vector<double> &cand,double L){
  double ans =1e10;

  rep(i,cand.size()){
    rep(j,vb.size())vb[j].real()+=cand[i];
    if (isok(va,vb,L) ){
      ans=min(ans,compute_width(va,vb));
    }
    rep(j,vb.size())vb[j].real()-=cand[i];
  }
  return ans;
}


main(){
  double L;
  while(cin>>L && L){
    vector<P> va,vb;
    P a;
    int n;
    cin>>n;
    rep(i,n){
      cin>>a.real()>>a.imag();
      va.pb(a);
    }
    
    int m;
    cin>>m;
    rep(i,m){
      cin>>a.real()>>a.imag();
      vb.pb(a);
    }

    vector<double> cand_a;
    vector<double> cand_b;
    rep(i,va.size()){
      rep(j,vb.size()){
	find_Ldif(mp(va[i],va[(i+1)%va.size()]),mp(vb[j],vb[(j+1)%vb.size()]),L,cand_a,cand_b);
      }
    }
    
    double ans =min(solve(va,vb,cand_a,L),solve(vb,va,cand_b,L));
    printf("%.8lf\n",ans);
  }
  
  return false;
}
accuracy: 1
time_ms: 2020
memory_kb: 1020
final_rank: 9