Pagini recente » Cod sursa (job #195626) | Cod sursa (job #1864399) | Cod sursa (job #578333) | Cod sursa (job #1530365) | Cod sursa (job #2725710)
#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");
if (fin == NULL) {
printf("Nu a putut fi deschis fisierul cmap.in\n");
return 0;
}
fscanf(fin, "%d", &n);
coord = malloc((n+1) * sizeof *coord);
// sort_y contine permutari ale indexilor
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;
}
// sort dupa coordonata x
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 calc_dist_min(int L, int R, int *sort_y, punct *coord) {
double d_min;
if (R-L < 4) {
double d_temp;
// 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 = calc_dist(sort_y[L], sort_y[L+1], coord);
// 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;
}
// 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 left = M+1, right = M+1;
for (int i = L; i <= M; i++) {
int p = sort_y[i];
// DOAR daca coord[p].x >= coord[M].x - lim
if (coord[p].x >= coord[M].x - lim) {
// cuprind toate punctele cu y in intervalul [coord[p].y - lim, coord[p].y + lim]
while (right < R && coord[sort_y[right]].y <= coord[p].y + lim) {
right += 1;
}
while (left < right && coord[sort_y[left]].y <= coord[p].y - lim) {
left += 1;
}
// calculez distanta de la p la toate punctele din interval
for (int j = left; j < right; j++) {
double temp_dist = calc_dist(sort_y[j], sort_y[i], coord);
if (temp_dist < d_min) d_min = temp_dist;
}
}
}
// MERGE
// similar cu merge sort, sortez local dupa coordonata y
int *temp_arr = malloc((R-L) * sizeof *temp_arr);
left = L;
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++;
}
// copiez din temp arr
for (int it = 0; it < R-L; it++) {
sort_y[L+it] = temp_arr[it];
}
free(temp_arr);
return d_min;
}