Pagini recente » Cod sursa (job #3293368) | Diferente pentru implica-te/arhiva-educationala intre reviziile 213 si 223 | Diferente pentru implica-te/arhiva-educationala intre reviziile 179 si 223 | Cod sursa (job #3294038) | Cod sursa (job #3291446)
#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;
}