Problem: Gaku decided to observe the ant's nest as a free study during the summer vacation. The transparent observation case that his grandpa prepared for his grandchildren is very unique and looks like Figure 1.

Ant nest
Figure 1



This case consists of two congruent convex polygons s1 and s2 and some rectangles. Place one of the rectangular faces other than s1 and s2 so that it touches the floor. Gogo, who started observing, noticed that the height of the soil changed depending on how the bottom was selected, even though the amount of soil contained was the same (Fig. 2).

Ant nest
Figure 2



Gogo wanted to know how high it would be depending on how the case was placed. Create a program that outputs the maximum value of the soil height by inputting the shape of the convex polygon s1, the distance d between s1 and s2, and the volume V of the soil. The soil shall level as soon as the bottom of the case is placed on the floor. The s1 shape of the transparent case is given by n vertices on the two-dimensional coordinate plane. These vertices are entered in a counterclockwise order. n is 3 or more and 100 or less, and d and V are integers of 1 or more and 10,000 or less, respectively. In addition, x and y of the coordinates (x, y) of the vertices of the polygon shall be integers of -1,000 or more and 1,000 or less, respectively. V does not exceed the volume of the case.



input

A sequence of multiple datasets is given as input. The end of the input is indicated by three zero lines. Each dataset is as follows.

1st line n d V (integer integer integer; half-width space delimited)
Coordinates of the first vertex on the second line x y (integer integer; half-width space delimited)
Coordinates of the second vertex on the third line
::
n + 1 Coordinates of the nth vertex on the 1st line


The number of datasets does not exceed 20.

output

Outputs the maximum soil height for each input dataset. The answer must not have an error greater than 0.00001.

Example

Input

4 1 1
0 0
1 0
1 2
0 2
0 0 0


Output

1.000000

Solution (in CPP):

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

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

using namespace std;

class Point{
public:
  double x,y;

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

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

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

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

};

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

};

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

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

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

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

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

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

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

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

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



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

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

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

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

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

double getArea(vector<Point>& vec) {
  double sum = 0;
  for(int i=0;i<vec.size();i++)
    sum += cross(vec[i],vec[(i+1)%vec.size()]);
  return fabs(sum)/2.0;
}


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


Point getCentroidOfConvex(Polygon& poly){
  double area = getArea(poly);
  int V = poly.size();
  assert( !equals(area,0.0) );
  double x = 0, y = 0;
  rep(i,(int)poly.size()) {
    x += ( poly[i].x + poly[(i+1)%V].x ) * ( poly[i].x*poly[(i+1)%V].y - poly[(i+1)%V].x*poly[i].y );
    y += ( poly[i].y + poly[(i+1)%V].y ) * ( poly[i].x*poly[(i+1)%V].y - poly[(i+1)%V].x*poly[i].y );
  }
  return Point(x/(6.0*area),y/(6.0*area));
}

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

/*
  360???????????£??¨?????? <= ?????????
  or
  ???????????§?±±???????????????,?????????????????§?????? 360????????????????????£????????£?????????

  ???????????§?????? ????????????(?????<)
  ?????´????????§????????¨?????????????????????

 */

bool DEBUG = 0;

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

int V;
double d,vol;
Polygon poly;
Point ps[110];

double lets_compute_arg(int L,int R){
  assert( L != R );
  Point lp = poly[L], rp = poly[R];
  //cout << lp << " " << rp << " ---" << endl;
  rp = rp - lp;
  lp = Point(0,0);
  //cout << lp << " " << rp << " ---" << endl;
  Vector e = rp / abs(rp);
  e = e * 100000;
  e = rotate(e,toRad(90.0));

  Line line = Line(e,e * -1);

  //cout << "heikou? " << line.p1-line.p2 << " " << poly[L]-poly[R] << " :: " << cross(line.p1-line.p2,poly[L]-poly[R]) << endl;
  assert( intersectLL(line,Line(poly[L],poly[R])) );
  Point cp = crosspoint(line,Line(poly[L],poly[R]));
  //cout << "cp = " << cp << endl;
  double ret = getArg(Point(0,-1000),Point(0,0),cp);
  //if( LT(ret,toRad(90.0)) ) ret = toRad(180.0) - ret;
  /*
  cout << "ret arg = " << ret * 180.0 / M_PI << endl;
  cout << rotate(cp,toRad(180.0)+ret) << endl;
  cout << rotate(poly[L],toRad(180.0)+ret) << endl;
  cout << rotate(poly[R],toRad(180.0)+ret) << endl;
  */
  return ret + toRad(180.0);
}


double getNewVolume(double h){
  Segment cut_line = Segment(Point(-20000,h),Point(20000,h));
  int nV = 0;
  //ps[0] = poly[0];
  
  int index = 0;
  int cross_ps[2];

  //cout << "cut_line = " << cut_line << endl;
  rep(i,V) {
    Segment seg = Segment(poly[i],poly[(i+1)%V]);
    if( intersectSS(cut_line,seg) ) { // ???????????´????????????
      Point cp = crosspoint(cut_line,seg);
      if( !( cp == seg.p1 || cp == seg.p2 ) ) {
        ps[nV++] = cp;
      } 
    } 
    ps[nV++] = poly[(i+1)%V];
  }


  rep(i,nV) if( equals(cut_line.p2.y,ps[i].y) ) {
    cross_ps[index++] = i;
  }

  /*
  cout << "H = " << h << endl;
  cout << "cutted poly = " << endl;
  rep(i,nV) {
    cout << ps[i] << endl;
  } puts("");

  cout << "index = " << index << endl;
  */

  assert( index == 2 );
  
  int sp = -1;
  double maxi_h = -1e30;
  rep(i,nV) maxi_h = max(maxi_h,ps[i].y);
  rep(i,nV) if( equals(maxi_h,ps[i].y) ) { sp = i; break; }
  assert( sp != -1 );  



  //cout << sp << " = " << cross_ps[0] << " or " << cross_ps[1] << endl;
  //cout << ps[sp] << endl;
  assert( ( cross_ps[0] != sp && cross_ps[1] != sp ) ); 
  bool found = false;
  int cur = sp;
  vector<Point> npoly;
  rep(i,nV) {
    bool same_point = ( cross_ps[0] == cur || cross_ps[1] == cur );
    if( same_point && found ) { npoly.push_back(ps[cur]); break; }
    if( same_point ) found = true;
    if( found ) npoly.push_back(ps[cur]);
    cur = ( cur + 1 ) % nV;
  }

  if( DEBUG ) {

    cout << "added polygon" << endl;
    rep(i,nV) {
      cout << ps[i] << endl;
    } cout << endl;

    cout << "cutted polygon" << endl;
    rep(i,npoly.size()){
      cout << npoly[i] << endl;
    }
  }

  double area = getArea(npoly);
  return area * d;
}

void compute(){

  bool full = false;
  {
    double area = getArea(poly) * d;
    if( equals(area,vol) ) full = true;
  }

  double maxi = 0;
  Point centroid = getCentroidOfConvex(poly);
  //cout << "centroid = " << centroid << endl;
  rep(i,V) poly[i] = poly[i] - centroid;
  centroid = Point(0,0);

  if( DEBUG ) {
    cout << "moved polygon" << endl;
    rep(i,V){
      cout << poly[i] << endl;
    } puts("");
  }

  rep(_,V){

    if( DEBUG ) {
      cout << "let's try" << endl;
      rep(i,V) {
        cout << poly[i] << endl;
      } puts("");
      }

    double maxi_y = -1e30, mini_y = 1e30;
    rep(i,V) maxi_y = max(maxi_y,poly[i].y), mini_y = min(mini_y,poly[i].y);
    double low_y = mini_y, high_y = maxi_y;

    if( !full ) {
      rep(__,60){
        double mid_y = ( low_y + high_y ) / 2.0;

        double new_volume = getNewVolume(mid_y);

        if( equals(new_volume,vol) ) { maxi = max(maxi,fabs(mid_y-mini_y)); break; }
        if( LT(new_volume,vol) ) low_y  = mid_y;
        else                     high_y = mid_y;
      }
    } else {
      rep(j,V) maxi = max(maxi,abs(mini_y-poly[j].y));
    }

    
    int left_p = -1, right_p = -1;
    rep(i,V) if( equals(mini_y,poly[i].y) ) {
      if( left_p == -1 ) left_p = i;
      if( right_p == -1 ) right_p = i;
      if( LT(poly[i].x,poly[left_p].x)  ) left_p  = i;
      if( LT(poly[right_p].x,poly[i].x) ) right_p = i;
    }

    /*
    rep(i,V){
      cout << poly[i] << "!" << endl;
    }
    */

    assert( left_p != right_p );
    assert( left_p != -1 && right_p != -1 );
    //cout << poly[left_p] << " => " << centroid << " => " << poly[right_p] << endl;
    ( left_p  += 1 ) %= V;
    ( right_p += 1 ) %= V;
    double rad = lets_compute_arg(left_p,right_p);
    //cout << "rad = " << rad * 180.0 / M_PI << endl;
    //assert( LT(rad * 180.0 / M_PI,180.0) );
    //rad = toRad(360.0) - rad;
    //cout << "rad = " << rad * 180.0 / M_PI << endl;
    rep(i,V) poly[i] = rotate(poly[i],rad);

  }
  printf("%.10f\n",maxi);
}

void fix(){
  bool update = true;
  while( update ){
    update = false;
    rep(i,poly.size()){
      int j = ( i + 1 ) % poly.size();
      int k = ( i + 2 ) % poly.size();
      if( equals(cross(poly[j]-poly[i],poly[k]-poly[i]),0.0) ) {
        update = true;
        poly.erase(poly.begin()+j);
        goto Skip;
      }
    }
  Skip:;
  }
  V = poly.size();
}

int main(){

  // ????????????????????±?????????????????????????????????????????¨
  
  int a,b,c;
  while( scanf("%d %d %d",&a,&b,&c), a|b|c ){
    V = a, d = b, vol = c;
    poly.clear();
    poly.resize(V);
    rep(i,V) scanf("%lf %lf",&poly[i].x,&poly[i].y);
    fix();
    compute();
  }
  return 0;
}