Pagini recente » Cod sursa (job #2499499) | Cod sursa (job #502680) | Cod sursa (job #2189328) | Cod sursa (job #3005117) | Cod sursa (job #2070522)
// closestPairOfPoints.cpp : Defines the entry point for the console application.
//
#include <fstream>
#include <vector>
#include <algorithm>
#include <limits>
#include <iostream>
using namespace std;
struct Point
{
double x;
double y;
Point();
Point(const double&, const double&);
double distanceTo(const Point&);
friend ostream& operator << (ostream&, const Point&);
};
class SortByX
{
public:
bool operator()(const Point&, const Point&);
};
class SortByY
{
public:
bool operator()(const Point&, const Point&);
};
double minSplitPairDistance(vector<Point> pX, vector<Point> pY, double currentMinDist)
{
double minDist = currentMinDist;
Point rightMostOnLeft = pX[pX.size() / 2 - 1];
vector<Point> candidates;
for (vector<Point>::iterator i = pY.begin(); i != pY.end(); i++)
if ((i->x <= rightMostOnLeft.x + currentMinDist) && (i->x >= rightMostOnLeft.x - currentMinDist))
candidates.push_back(*i);
for (int i = 0; i < candidates.size(); i++)
{
int maxPos;
if (i + 8 >= candidates.size())
maxPos = candidates.size() - 1;
else
maxPos = i + 8;
for (int j = i + 1; j <= maxPos; j++)
if (candidates[i].distanceTo(candidates[j]) < minDist)
minDist = candidates[i].distanceTo(candidates[j]);
}
return minDist;
}
Point::Point()
{
x = 0;
y = 0;
}
Point::Point(const double& xCoord, const double& yCoord)
{
x = xCoord;
y = yCoord;
}
ostream& operator << (ostream& os, const Point& a)
{
os << "(" << a.x << ", " << a.y << ")";
return os;
}
double Point::distanceTo(const Point& other)
{
double xDist = x - other.x;
double yDist = y - other.y;
return sqrt((xDist * xDist) + (yDist * yDist));
}
bool SortByX::operator()(const Point& a, const Point& b)
{
return (a.x < b.x);
}
bool SortByY::operator()(const Point& a, const Point& b)
{
return (a.y < b.y);
}
double minDistanceBetweenPoints(vector<Point> points, vector<Point> pX, vector<Point> pY)
{
int size = points.size();
if (size <= 3) // base case for recursion: brute force on small input size
{
double bestDistance = numeric_limits<double>::max();
for (vector<Point>::iterator i = points.begin(); i != points.end(); i++)
for (vector<Point>::iterator j = i + 1; j != points.end(); j++)
if (i->distanceTo(*j) < bestDistance)
bestDistance = i->distanceTo(*j);
return bestDistance;
}
else
{
double separator;
if (size % 2 == 0)
separator = (pX[size / 2].x + pX[size / 2 - 1].x) / 2;
else
separator = pX[size / 2].x;
vector<Point> pLeft, pRight, xLeft, xRight, yLeft, yRight;
for (vector<Point>::iterator i = points.begin(); i != points.end(); i++)
{
if (i->x <= separator)
pLeft.push_back(*i);
else
pRight.push_back(*i);
}
for (vector<Point>::iterator i = pX.begin(); i != pX.end(); i++)
{
if (i->x <= separator)
xLeft.push_back(*i);
else
xRight.push_back(*i);
}
for (vector<Point>::iterator i = pY.begin(); i != pY.end(); i++)
{
if (i->x <= separator)
yLeft.push_back(*i);
else
yRight.push_back(*i);
}
double minDistLeft = minDistanceBetweenPoints(pLeft, xLeft, yLeft);
double minDistRight = minDistanceBetweenPoints(pRight, xRight, xLeft);
double delta = min(minDistLeft, minDistRight);
double minDistSplit = minSplitPairDistance(pX, pY, delta);
double result = min(delta, minDistSplit);
return result;
}
}
int main()
{
ifstream fin("cmap.in");
ofstream fout("cmap.out");
vector<Point> points;
int n;
fin >> n;
while (n)
{
double tempX, tempY;
fin >> tempX >> tempY;
points.push_back(Point(tempX, tempY));
n--;
}
vector<Point> pX = points, pY = points;
sort(pX.begin(), pX.end(), SortByX());
sort(pY.begin(), pY.end(), SortByY());
fout << minDistanceBetweenPoints(points, pX, pY);
return 0;
}