Cod sursa(job #2320972)

Utilizator Andreea_DanielaAndreea Guster Andreea_Daniela Data 15 ianuarie 2019 15:03:54
Problema Cele mai apropiate puncte din plan Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.51 kb
// Guster Andreea 15.01.2019
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

#define x first 
#define y second 

using namespace std;

typedef pair<int, int> Point;

bool cmpY(Point p1, Point p2) {
	return p1.y > p2.y;
}

double distance(Point p1, Point p2) {
	return sqrt((p1.x - p2.x) * (p1.x -p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double minimum( vector<Point> &array) {
   
	double MIN = 0x3f3f3f3f;// DBL_MAX;
	for (unsigned int i = 0; i < array.size() - 1; i++)
		for (unsigned int j = i + 1; j < array.size(); j++)
			if (distance(array[i], array[j]) < MIN)
				MIN = distance(array[i], array[j]);
	return MIN;
}

double dividePlane(vector<Point> &Y, vector<Point> &X, int left, int right) {  //X[left...right]
	double dist;

	if (right - left + 1 < 4) {
		dist = minimum(X);
	}
	else {
		int counter = 0;
		int middle = (right + left) / 2;
		
		vector<Point> Yleft, Yright;
		Yleft.resize(middle - left + 1);
		Yright.resize(right - middle + 1);

		for (int i = left; i <= middle; i++) {
			Yleft[counter++] = X[i];
		}

		counter = 0;

		for (int i = middle + 1; i <= right; i++) {
			Yright[counter++] = X[i];
		}

		double distLeft = dividePlane(Yleft, X, left, middle);   //X[left ...middle]
		double distRight = dividePlane(Yright, X, middle + 1, right);  //X[middle+1 ....right]

		dist = min(distLeft, distRight);

		vector<Point> MiddleStrip;                        //fasia facuta prin trasarea derptei verticale M de dimensiune 2*dist, pe aceasta fasie pot exista maxim 8 pct
		
		for (unsigned i = 0; i < X.size(); i++) {                //vectorul MiddleStrip este vectorul care contine punctele din interiorul fasiei
			if ( abs(X[i].x - X[middle].x) < dist) {
				MiddleStrip.push_back(X[i]);
			}
        }
		
		double MIN = 0x3f3f3f3f;//DBL_MAX;
		for (unsigned i = 0; i < MiddleStrip.size() - 1; i++) {                        //vad care punct este cel mai aproape de liniva verticala middle
			for (unsigned j = i + 1; j < MiddleStrip.size(); j++)  // && (MiddleStrip[j].y - MiddleStrip[i].y < MIN)
				if (distance(MiddleStrip[i], MiddleStrip[j]) < MIN)
					MIN = distance(MiddleStrip[i], MiddleStrip[j]);
		}
		dist = min(dist, MIN);
	}

	return dist;
}

int main() {
	ifstream fin("cmap.in");
	ofstream fout("cmap.out");

	int sizePoints;
	vector<Point> Points;
	vector<Point> PointsX, PointsY;

	fin >> sizePoints;
	Points.resize(sizePoints);
	PointsX.resize(sizePoints);
	PointsY.resize(sizePoints);

	//cout << "Cate puncte sunt in plan: " << sizePoints << "\n";
	for (int i = 0; i < sizePoints; i++) {
		fin >> Points[i].x >> Points[i].y;
		
		PointsX[i] = PointsY[i] = Points[i];
	}
	fin.close();
	/*
	cout << "Afiseaza punctele din plan:\n";
	for (int i = 0; i < sizePoints; i++) {
		cout << Points[i].x << " " << Points[i].y << "\n";
	}
	*/
	sort(PointsX.begin(), PointsX.end());   //ordonez crescator dupa abscisa
	sort(PointsY.begin(), PointsY.end(), cmpY);  //ordonex descrescator dup ordonata

	/**
	cout << "Punctele ordonate dupa abscisa:\n";
	for (auto point : PointsX)
		cout << point.x << " " << point.y << "\n";

	cout << "\nPunctele ordonate dupa ordonata:\n";
	for (auto point : PointsY)
		cout << point.x << " " << point.y << "\n";

	cout << "\nCea mai mica distanta intre 2 puncte este: " << dividePlane(PointsY, PointsX, 0, Points.size() - 1) << "\n";*/
	fout << dividePlane(PointsY, PointsX, 0, Points.size() - 1);
	fout.close();

	//system("pause");
	return 0;
}