Cod sursa(job #2070522)

Utilizator stefann98Stefan Nita stefann98 Data 19 noiembrie 2017 17:32:07
Problema Cele mai apropiate puncte din plan Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.86 kb
// 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;
}