#include<iostream>
#include<cmath>
#include<cstdio>
#include<cassert>
#include<climits>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<iomanip>
#include<queue>

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

using namespace std;

// Library - template - begin

class Point{
public:
  long double x,y;

  Point(long double x = -IINF,long double y = -IINF): 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 * (long double a){return Point(a*x,a*y);}
  Point operator / (long 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: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& p)const { return p.p1 == p1 && p.p2 == p2; }
};

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

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

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

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

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

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

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

// Library - template - end

// Library - CCW - begin

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

// Library - CCW - end

// Library - intersect - begin
 
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) {
  long 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;
}
long double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}

long double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

long double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}

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

long 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){
  long double A = cross(l.p2-l.p1,m.p2-m.p1);
  long 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);
}

// Library - intersect - end

// Library - Voronoi - begin

class Voronoi
{
public:
  Polygon poly;
 
  Voronoi(Polygon poly):poly(poly){}

  Point polar(long double a,long double rad){ return Point(a*cos(rad),a*sin(rad)); }
 
  long double args(Point p){ return atan2(p.y,p.x); }
 
  Point project(Segment s,Point p){
    Point base = s.p2 - s.p1;
    long double t = dot(p-s.p1,base)/norm(base);
    return s.p1+base*t;
  }
 
  Point reflect (Segment s, Point p){ return p + (project(s,p)-p)*2.0; }
  
  bool isIntersect(Point p1,Point p2,Point p3,Point p4){
    return (ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0 && ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0 );
  }
 
  bool isIntersect(Segment s1,Segment s2){
    return isIntersect(s1.p1,s1.p2,s2.p1,s2.p2);
  }

  Point getCrossPointSegments(Segment s1,Segment s2){
    //assert(isIntersect(s1,s2));
    Point base = s2.p2 - s2.p1;
    long double d1 = abs(cross(base,s1.p1-s2.p1));
    long double d2 = abs(cross(base,s1.p2-s2.p1));
    long double t = d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
  }


  Point getCrossPointLines( Line s1, Line s2){
    Point a = s1.p2 - s1.p1;
    Point base = s2.p2 -s2.p1;
    return s1.p1 + a * (cross(base, s2.p1 - s1.p1)/cross(base, a));
  }

  Polygon cutPolygon( Polygon P, Line l ){
    Polygon u;
    
    for ( int i = 0; i < P.size(); i++ ){
      Point a = P[i], b = P[(i+1)%P.size()];
	
      if ( ccw(l.p1, l.p2, a) != CLOCKWISE ) u.push_back(a);
      if ( ccw(l.p1, l.p2, a) * ccw(l.p1, l.p2, b) == -1 ){
	u.push_back(getCrossPointLines(Segment(a, b), l));
      }
    }   
    return u;
  } 
 
  Line CreateLine(Point p,Point pp){
    Point mid = (p+pp)/2;
    Point sl = pp-p;//原点に5
    long double rad = args(sl);
    Point ap = polar(abs(sl),rad+M_PI/2)+mid;
    //ap.x = abs(sl)*cos(rad+M_PI/2)+mid.x;
    //ap.y = abs(sl)*sin(rad+M_PI/2)+mid.y;
    return Line(mid,ap);
  } 
 
  long double AreaCalc(Polygon p){
    long double area = 0;
    for(int i=0;i<p.size();i++)
      area+=cross(p[i],p[(i+1)%p.size()]);
    return fabs(area)/2.0;
  } 

  //サイトposに対するボロノイセルV(pos)の面積を返す 
  //pointsは多角形の中に存在するサイトの集合]
  //posはpoints中の自分の位置
  Polygon getVoronoi(vector<Point>& points,int pos){
    Polygon polx = poly;
    int N = points.size();
    for(int i=0;i<N;i++)
      if(i != pos)
	polx = cutPolygon(polx,CreateLine(points[pos],points[i]));
    return polx;
  }  

};

// Library - Voronoi - end

struct Data{
  Segment seg;
  long double score;
  int index;
  Data(Segment seg=Segment(),long double score=IINF,int index=IINF):seg(seg),score(score),index(index){}
  bool operator < (const Data& data)const { return score > data.score; }
};

double H,W;
int V;
Polygon poly;
vector<Point> points;
vector<Data> vec;
vector<int> sp,gp;

int par[MAX],urank[MAX];
int N;

inline void init(){ rep(i,N)par[i] = i, urank[i] = 0; }

int find(int x){
  if( x == par[x] ) return x;
  return par[x] = find(par[x]);
}

void unit(int x,int y){
  x = find(x), y = find(y);
  if( x != y ){
    if( urank[x] < urank[y] ) par[x] = y;
    else{
      par[y] = x;
      if( urank[x] == urank[y] )urank[x]++;
    }
  }
}

inline bool check(){
  rep(i,sp.size()){
    rep(j,gp.size()){
      if(par[sp[i]] == par[gp[j]])return true;
    }
  }
  return false;
}

Point CLEAR(Point p){
  p.x *= 100000;
  p.x = floor(p.x);
  p.x /= 100000;
  p.y *= 100000;
  p.y = floor(p.y);
  p.y /= 100000;
  return p;
}

int main(){
  poly.clear();
  points.clear();
  cin >> W >> H >> V;
  points.resize(V);
  poly.push_back(Point(0,0));  poly.push_back(Point(W,0));  
  poly.push_back(Point(W,H));  poly.push_back(Point(0,H));  
  rep(i,V)cin >> points[i].x >> points[i].y;
  vec.clear();

  Voronoi vor = Voronoi(poly);
  rep(i,V){
    Polygon tmp = vor.getVoronoi(points,i);
    rep(j,tmp.size()){
      long double score = IINF;
      Segment seg = Segment(CLEAR(tmp[j]),CLEAR(tmp[(j+1)%(int)tmp.size()]) );

      rep(k,V) score = min(score,distanceSP(seg,points[k]));
      vec.push_back(Data(seg,score,i));
      //cout << vec.back().seg << " " << vec.back().score << endl;
    }
  }

  map<Point,int> getIndex;
  int dex = 0;
  rep(i,vec.size()){
    if(getIndex.find(vec[i].seg.p1) == getIndex.end())getIndex[vec[i].seg.p1] = dex++;
    if(getIndex.find(vec[i].seg.p2) == getIndex.end())getIndex[vec[i].seg.p2] = dex++;
  }

  sp.clear();
  gp.clear();
  rep(i,vec.size()){
    if( equals(vec[i].seg.p1.y,0) )sp.push_back(getIndex[vec[i].seg.p1]);
    if( equals(vec[i].seg.p2.y,0) )sp.push_back(getIndex[vec[i].seg.p2]);
    if( equals(vec[i].seg.p1.y,H) )gp.push_back(getIndex[vec[i].seg.p1]);
    if( equals(vec[i].seg.p2.y,H) )gp.push_back(getIndex[vec[i].seg.p2]);

  }


  N = dex;

  init();

  sort(vec.begin(),vec.end());
  int cur = 0;
  long double ans = -1;
  while(!check()){
    assert( cur < vec.size() );
    unit(getIndex[vec[cur].seg.p1],getIndex[vec[cur].seg.p2]);
    if( ans == -1 )ans = vec[cur++].score;
    else           ans = min(ans,vec[cur++].score);
    rep(i,N)find(i);
  }

  cout << setiosflags(ios::fixed) << setprecision(3) << ans << endl;
  return 0;
}

Measured memory_bytes: 1728