Cod sursa(job #2072433)

Utilizator dark_knight2012Potec Tiberiu dark_knight2012 Data 21 noiembrie 2017 20:48:37
Problema Cele mai apropiate puncte din plan Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.09 kb
#include <fstream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cmath>
#include <limits>

using namespace std;

ifstream in ("cmap.in");
ofstream out ("cmap.out");

struct punct
{
	int x;
	int y;
};

int sortare_x(punct a, punct b)
{
	return a.x < b.x;
}

int sortare_y(punct a, punct b)
{
	return a.y < b.y;
}

int citire(vector<punct> &v, vector <punct> &vx, vector<punct> &vy)
{
	int n;
	int aux_x;
	int aux_y;
	punct aux;
	in >> n;
	for (int i = 0; i < n; ++i)
	{
		in >> aux_x;
		in >> aux_y;
		aux.x = aux_x;
		aux.y = aux_y;
		v.push_back(aux);
		vx.push_back(aux);
		vy.push_back(aux);
	}
	sort(vx.begin(), vx.end(), sortare_x);
	sort(vy.begin(), vy.end(), sortare_y);
}

int afisare_vector(std::vector<punct> v)
{
	for (auto it : v)
	{
		out << it.x << " " << it.y << endl;
	}
	return 1;
}

float distanta_euclidiana(punct a, punct b)
{
	float distanta;
	distanta = sqrt( pow((a.x - b.x), 2) + pow((a.y - b.y), 2));
	return distanta;
}

float distanta_minima_aux(vector <punct> aux, int naux, float d)
{
	float min = d; /// distanta minima este presupusa initial ca fiind cea minima gasita in una din partile stangi sau drepti a vectorului
	vector <punct> :: iterator it;
	vector <punct> :: iterator it1;
	for (it = aux.begin(); it != aux.end(); it++)
	{
		for (it1 = it + 1; it1 != aux.end(); it1++)
		{
			if ( (*it1).y - (*it).y  < min )/// verificam daca cele doua puncte selectate au diferenta coordonatelor y mai mica decat d minima
			{
				if (distanta_euclidiana(*it, *it1) < min) /// daca distanta celor doua puncte e mai mica decat minimul actual
				{
					min =  distanta_euclidiana(*it, *it1); ///actualizam minimul
				}
			}
		}
	}
	return min;
}

float gaseste_dist_minima(vector <punct> vx, vector <punct> vy, int n)
{
	float d;
	float dmin = 100;

	vector <punct> :: iterator it;
	vector <punct> :: iterator it1;

	if (n <= 3) /// daca sunt mai putin de 3 puncte, folosim algoritmul banal de gasire a distantei
	{
		for (it = vx.begin(); it != vx.end(); it++)
		{
			for (it1 = it + 1; it1 != vx.end(); it1++) /// parcurgem fiecare element cu fiecare element si calculam distanta minima
			{
				d = distanta_euclidiana(*it, *it1);
				if (d < dmin)
				{
					dmin = d;
				}
			}
		}
		return dmin;
	}

	int mij = n / 2;
	punct punct_median = vx.at(mij);

	vector <punct> vy_left; /// vector sortat dupa y in care punem elementele din partea stanga a medianei vectorului
	vector <punct> vy_right; /// vector sortat dupa y in care punem elementele din partea dreapta a medianei vectorului

	for (auto it : vy)
	{
		if (it.x <= punct_median.x) /// daca punctul e in partea stanga
		{
			vy_left.push_back(it); /// inseram in vectorul stang
		}
		else
		{
			vy_right.push_back(it); /// daca nu, in cel drept
		}
	}

	float distanta_left = gaseste_dist_minima(vx, vy_left, mij); /// calculam recursiv cea mai mica distanta dintre doua puncte in partea stanga

	vector<punct> vx_right (&vx[mij], &vx[n]); /// vx_right este doar partea dreapta copiata din vectorul vx pe care o trimit in functia de mai jos

	float distanta_right = gaseste_dist_minima(vx_right, vy_right, n - mij); /// calculam recursiv cea mai mica distanta dintre doua puncte in partea dreapta

	d = min(distanta_left, distanta_right); /// luam distanta minima

	vector <punct> aux; /// vectorul aux va contine elementele de o parte si de alta care au distanta (de la coorodnatele x) < d gasita minima

	for (auto it : vy)
	{
		if (abs(it.x - punct_median.x) < d)
		{
			aux.push_back(it);
		}
	}
	int naux = aux.size();
	return min(d, distanta_minima_aux(aux, naux, d)); /// la final, afisez minimul dintre distanta minima gasita in cele 2 parti si cea pe care o voi gasi in elementele de o parte si de alta a vectorului

}


int main()
{
	vector <punct> v; /// vectorul initial
	vector <punct> vx; /// vectorul initial sortat dupa x
	vector <punct> vy; /// vectorul initial sortat dupa y
	citire(v, vx, vy);
	int lungime = v.size();
	//afisare_vector(v);
	out<<gaseste_dist_minima(vx,vy,lungime);
	return 0;
}