#include #include #include #include #include using namespace std; typedef pair Punto; float distanciaAlCuadrado(const Punto & p1, const Punto & p2) { float a = p2.first - p1.first; float b = p2.second - p1.second; return a * a + b * b; } bool compararY(const Punto & p1, const Punto & p2) { return p1.second < p2.second; } float distanciaAlCuadradoMinima(const vector & puntosPorX, const vector & puntosPorY) { int talla = puntosPorX.size(); if (talla == 2) return distanciaAlCuadrado(puntosPorX[0], puntosPorX[1]); if (talla == 3) return min({distanciaAlCuadrado(puntosPorX[0], puntosPorX[1]), distanciaAlCuadrado(puntosPorX[0], puntosPorX[2]), distanciaAlCuadrado(puntosPorX[1], puntosPorX[2])}); int tallaIzquierda = talla / 2; vector puntosIzquierdaPorX(puntosPorX.begin(), puntosPorX.begin() + tallaIzquierda), puntosDerechaPorX(puntosPorX.begin() + tallaIzquierda, puntosPorX.end()); vector puntosIzquierdaPorY(tallaIzquierda), puntosDerechaPorY(talla - tallaIzquierda); for (int i = 0, j = 0, k = 0; i < talla; i++) if (puntosPorY[i] < puntosDerechaPorX[0]) puntosIzquierdaPorY[j++] = puntosPorY[i]; else puntosDerechaPorY[k++] = puntosPorY[i]; float minimaIzquierda = distanciaAlCuadradoMinima(puntosIzquierdaPorX, puntosIzquierdaPorY); float minimaDerecha = distanciaAlCuadradoMinima(puntosDerechaPorX, puntosDerechaPorY); float minima = min(minimaIzquierda, minimaDerecha); vector puntosCentralesPorY; float frontera = puntosIzquierdaPorX[tallaIzquierda - 1].first; for (auto p : puntosPorY) if ( abs(frontera - p.first) < minima ) puntosCentralesPorY.push_back(p); for (int i = 0; i < puntosCentralesPorY.size() - 1; i++) for (int j = i + 1; j < puntosCentralesPorY.size() && puntosCentralesPorY[j].second - puntosCentralesPorY[i].second < minima; j++) minima = min(minima, distanciaAlCuadrado(puntosCentralesPorY[i], puntosCentralesPorY[j])); return minima; } float distanciaMinima(const vector & puntos) { if (puntos.size() < 2) throw string("Necesitamos al menos dos puntos."); vector puntosPorX(puntos); sort(puntosPorX.begin(), puntosPorX.end()); for (int i = 0; i < puntosPorX.size() - 1; i++) if (puntosPorX[i] == puntosPorX[i + 1]) return 0; vector puntosPorY(puntos); sort(puntosPorY.begin(), puntosPorY.end(), compararY); return sqrt(distanciaAlCuadradoMinima(puntosPorX, puntosPorY)); } int main () { default_random_engine default_random; uniform_real_distribution generadorAleatorio(-1000.0, 1000.0); vector puntos; for (int talla = 2, tallaMax = 10; tallaMax <= 100000; tallaMax *= 10) for (; talla < tallaMax; talla += tallaMax / 10) { while(puntos.size() < talla) puntos.push_back(Punto(generadorAleatorio(default_random), generadorAleatorio(default_random))); float distancia = distanciaMinima(puntos); cout << talla << "\t" << distancia << endl; } }