Cod sursa(job #2066330)

Utilizator StriddRobert Stridd Data 14 noiembrie 2017 21:41:32
Problema Cele mai apropiate puncte din plan Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.23 kb
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cmath>

using namespace std;

struct Punct{
    int x;
    int y;
};

// Distanta pentru R^2
double returnDist(Punct& P1,Punct& P2)
{
    return sqrt((P2.x - P1.x)*(P2.x - P1.x) + (P2.y - P1.y)*(P2.y - P1.y));
}

// Functia de comparare pentru vectorul ordonat dupa x
int compByXCoord(Punct& A1, Punct& A2)
{
    if(A1.x == A2.x)
        return A1.y < A2.y;
    return A1.x < A2.x;
}
// Functia de comparare pentru vectorul ordonat dupa y
int compByYCoord(Punct& A1, Punct& A2)
{
    if(A1.y == A2.y)
        return A1.x < A2.x;
    return A1.y < A2.y;
}

// Pentru 4 puncte, calculam direct cea mai mica distanta
double bruteForce4Points(int n, vector<Punct> &Puncte)
{
    int i, j;
    double minDist = 1000000;
    for(i = 0; i < n - 1; i++)
        for(j = i + 1; j < n; j++)
            if(minDist > returnDist(Puncte[i],Puncte[j]))
                minDist = returnDist(Puncte[i],Puncte[j]);
    return minDist;
}

// Comparare de float-uri, se putea folosi min
float minF(float x, float y)
{
    if(x > y)
        return y;
    return x;
}

/*
    La acest pas consideram toate punctele ordonate dupa Y si comparam
    cu distanga minima pana la acest pas. Distanga se actualizeaza cand gaseste
    o pereche a carei distanta este mai mica decat cea actuala.


*/
float searchVerticalSection(vector<Punct> &vertSect, float distance)
{
    float min = distance;
    for (int i = 0; i < vertSect.size() - 1; i ++)
        for (int j = i + 1; j < vertSect.size() &&
               (vertSect[j].y - vertSect[i].y) < min; j++ )
            if ( returnDist(vertSect[i], vertSect[j]) < min)
                min = returnDist(vertSect[i], vertSect[j]);

    return min;
}

float closPointsDivide(vector<Punct> &PuncteX,vector<Punct> &PuncteY, int dim)
{
    if (dim <= 4)
        return bruteForce4Points(dim, PuncteX);
    int middle =  dim / 2;

    vector<Punct> leftY;
    vector<Punct> rightY;

    int i;
    for(i = 0 ; i < dim; i++)
    {
        if(PuncteY[i].x <= PuncteX[dim/2].x)
            leftY.push_back(PuncteY[i]);
        else
            rightY.push_back(PuncteY[i]);
    }

    float minDistLeft = closPointsDivide(PuncteX,leftY, middle);
    float minDistRight = closPointsDivide(PuncteX,rightY, dim - middle);

    float dist = min(minDistLeft, minDistRight);

    vector<Punct> vertSect;
    int j = 0;
    for(int i = 0 ; i < dim; i++)
    {
        if(abs(PuncteY[i].x - PuncteX[middle].x) < dist )
            vertSect.push_back(PuncteY[i]);
    }
    return min(dist, searchVerticalSection(vertSect,dist) );
}

int main()
{
    vector<Punct> pointsX;
    vector<Punct> pointsY;
    ifstream fileRead("cmap.in");
    ofstream fileWrite("cmap.out");
    int nrPoints, i;

    Punct P;

    fileRead >> nrPoints;

    for(i = 0 ; i < nrPoints; i++)
    {
        fileRead >> P.x;
        fileRead >> P.y;
        pointsX.push_back(P);
        pointsY.push_back(P);
    }


    sort(pointsX.begin(),pointsX.end(),compByXCoord);
    sort(pointsY.begin(),pointsY.end(),compByYCoord);

    fileWrite << closPointsDivide(pointsX, pointsY, nrPoints);

    return 0;
}