Cod sursa(job #2725755)

Utilizator trucker4lifeMoraru Radu-Andrei trucker4life Data 19 martie 2021 16:54:49
Problema Cele mai apropiate puncte din plan Scor 50
Compilator c-64 Status done
Runda Arhiva educationala Marime 3.9 kb
#include <stdio.h>
#include <math.h>
#include <stdlib.h>


typedef struct {
    int x, y, val;
} punct;

double calc_dist(int p1, int p2, punct *coord) {
    return sqrt(pow(coord[p1].x - coord[p2].x, 2) +
                pow(coord[p1].y - coord[p2].y, 2));
}

double calc_dist_min(int L, int R, int *sort_y, punct *coord);

int comparator(const void *a, const void *b);

int main() {
    int n;
    int *sort_y;
    punct *coord;
    double dist_min;

    FILE *fin = fopen("cmap.in", "r");
    FILE *fout = fopen("cmap.out", "w");

    fscanf(fin, "%d", &n);
    coord = malloc((n+1) * sizeof *coord);

    sort_y = malloc((n+1) * sizeof *sort_y);

    for (int i = 1; i <= n; i++) {
        fscanf(fin, "%d %d", &(coord+i)->x, &(coord+i)->y);
        coord[i].val = i;
    }

    qsort(coord+1, n+1, sizeof *coord, comparator);
    for (int i = 0; i <= n; i++) {
        sort_y[i] = i;
    }

    dist_min = calc_dist_min(1, n+1, sort_y, coord);
    fprintf(fout, "%.6f", dist_min);

    free(coord);
    return 0;
}

int comparator(const void *a, const void *b) {
    punct *p1 = (punct *)a;
    punct *p2 = (punct *)b;

    if (p1->x == p2->x) {
        if (p1->y == p2->y)     return 0;
        else if (p1->y > p2->y) return 1;
        return -1;
    }
    else if (p1->x > p2->x)     return 1;
    return -1;
}

double min_interval(int L, int R, int *sort_y, punct*coord) {
    double d_min = calc_dist(sort_y[L], sort_y[L+1], coord);
    double d_temp;
    // incerc toate posibilitatile
    for (int i = L; i < R; i++) {
        for (int j = L; j < i; j++) {
            d_temp = calc_dist(sort_y[i], sort_y[j], coord);
            if (d_temp < d_min) d_min = d_temp;     // trebuie sa initializez d_min;
        }
    }
    return d_min;
}

double calc_dist_min(int L, int R, int *sort_y, punct *coord) {

    double d_min;

    if (R-L < 4) {
        // insertion sort dupa coordonata y
        for (int i = L+1; i < R; i++) {
            int t_y = sort_y[i];
            int j = i;

            while (j > L && coord[t_y].y < coord[sort_y[j-1]].y) {
                sort_y[j] = sort_y[j-1];
                j--;
            }
            sort_y[j] = t_y;
        }

        d_min = min_interval(L, R, sort_y, coord);
        return d_min;
    }

    // INTERVAL MARE

    int M = (L+R-1)/2;
    double dL = calc_dist_min(L, M+1, sort_y, coord);
    double dR = calc_dist_min(M+1, R, sort_y, coord);

    d_min = dR;
    if (dL < dR) d_min = dL;

    double lim = d_min;

    int *temp_arr = malloc((R-L) * sizeof *temp_arr);

    int left = L;
    int right = M+1;
    int i = 0;
    while (left < M+1 && right < R) {
        int lp = sort_y[left];
        int rp = sort_y[right];

        if (coord[lp].y < coord[rp].y) {
            temp_arr[i] = lp;
            left++;
        }
        else {
            temp_arr[i] = rp;
            right++;
        }
        i++;
    }

    // adaug restul
    while (right < R) {
        temp_arr[i] = sort_y[right];
        right++;
        i++;
    }
    while (left < M+1) {
        temp_arr[i] = sort_y[left];
        left++;
        i++;
    }

    int *puncte = malloc((R-L) * sizeof *puncte);
    // am punctele sortate dupa y, le iau pe cele de care am nevioe
    i = 0;
    for (right = 1; right < R-L; right++) {
        if (coord[temp_arr[right]].x >= coord[M].x - lim &&
            coord[temp_arr[right]].x <= coord[M].x + lim) {

            puncte[i] = temp_arr[right];
            i++;
        }
    }

    left = 0;
    for (right = 1; right < i; right++) {
        while (coord[puncte[left]].y < coord[puncte[right]].y - lim) {
            left++;
        }
        for (int it = left; it < right; it++) {
            double temp_dist = calc_dist(puncte[it], puncte[right], coord);
            if (temp_dist < d_min) d_min = temp_dist;
        }
    }

    // copiez din temp arr
    for (int it = 0; it < R-L; it++) {
        sort_y[L+it] = temp_arr[it];
    }

    free(temp_arr);
    free(puncte);

    return d_min;
}