Cod sursa(job #3291446)

Utilizator merlin32State Tudor-Alexandru merlin32 Data 4 aprilie 2025 18:38:15
Problema Cele mai apropiate puncte din plan Scor 50
Compilator c-64 Status done
Runda Arhiva educationala Marime 3.11 kb
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>


typedef struct
{
    int x;
    int y;

} Punct;

int compareY(const void *A, const void *B)
{
    Punct *vA = (Punct*)A;
    Punct *vB = (Punct*)B;
    if (vA->y < vB->y)
        return -1;
    if (vA->y > vB->y)
        return 1;
    return 0;
}

int compareX(const void *A, const void *B)
{
    Punct *vA = (Punct*)A;
    Punct *vB = (Punct*)B;
    if (vA->x < vB->x)
        return -1;
    if (vA->x > vB->x)
        return 1;
    if (vA->x == vB->x)
        return compareY(A, B);
    return 0;
}

double distance(Punct A, Punct B)
{
    return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}

double solveTrivial(Punct *v, int st, int dr)
{
    double AB = distance(v[st], v[st+1]);
    double AC = distance(v[st], v[dr]);
    double BC = distance(v[st+1], v[dr]);
    return (AB < AC) ? AB : ((AC < BC) ? AC : BC);
}

double minDistance(Punct *v, int st, int dr)
{
    if (dr - st + 1 == 3)
        return solveTrivial(v, st, dr);
    if (dr - st + 1 == 2)
        return distance(v[st], v[dr]);
    if (dr == st)
        return INFINITY;

    int mid = (st + dr) / 2;
    double leftDistance = minDistance(v, st, mid);
    double rightDistance = minDistance(v, mid + 1, dr);
    double initialMin = leftDistance < rightDistance ? leftDistance : rightDistance;

    int n2 = 0;
    Punct *y = (Punct*)calloc(dr - st + 1, sizeof(Punct));
    if (y == NULL)
    {
        puts("Eroare la alocare: y");
        exit(EXIT_FAILURE);
    }
    for (int i = st; i < dr; i++)
        if (abs(v[i].x - v[mid].x) < initialMin)
        {
            n2++;
            y[n2 - 1] = v[i];
        }
    if (n2 == 0)
    {
        free(y);
        return initialMin;
    }

    if (n2 > 1)
        qsort(y, n2, sizeof(Punct), compareY);
    double finalMin = initialMin;
    for (int i = 0; i < n2 - 1; i++)
        for (int j = i + 1; j < i + 7 && j < n2; j++)
        {
            double aux = distance(y[i], y[j]);
            if (finalMin > aux)
                finalMin = aux;
        }
    free(y);
    return finalMin;

}


int main()
{
    FILE *in, *out;
    in = fopen("cmap.in", "r");
    if (in == NULL)
    {
        puts("Eroare la deschidere: cmap.in");
        exit(EXIT_FAILURE);
    }
    int n1;
    fscanf(in, "%d", &n1);
    if (n1 < 2)
    {
        puts("Nu exista suficiente puncte!");
        exit(EXIT_FAILURE);
    }
    Punct *v = (Punct*)calloc(n1, sizeof(Punct));
    if (v == NULL)
    {
        puts("Eroare la alocare: v");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < n1; i++)
    {
        fscanf(in, "%d", &v[i].x);
        fscanf(in, "%d", &v[i].y);
    }
    if (fclose(in) < 0)
    {
        puts("Eroare la inchidere: cmap.in");
        exit(EXIT_FAILURE);
    }
    qsort(v, n1, sizeof(Punct), compareX);
    out = fopen("cmap.out", "w");
    if (out == NULL)
    {
        puts("Eroare la inchidere: cmap.out");
        exit(EXIT_FAILURE);
    }
    fprintf(out, "%.6f", minDistance(v, 0, n1 - 1));
    free(v);
    if (fclose(out) < 0)
    {
        puts("Eroare la inchidere: cmap.out");
        exit(EXIT_FAILURE);
    }
    return 0;
}