Cod sursa(job #3132187)

Utilizator ristinaCristina Savin ristina Data 21 mai 2023 23:51:31
Problema Cele mai apropiate puncte din plan Scor 100
Compilator c-64 Status done
Runda Arhiva educationala Marime 4.49 kb
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <assert.h>

#define EPS 0.000001

typedef struct Punct{
    long int x;
    long int y;
}Punct;

int compare_x(const void *a, const void *b) {

    Punct *punctA = (Punct *)a;
    Punct *punctB = (Punct *)b;

    return (int)(punctA->x - punctB->x);
}

int compare_y(const void *a, const void *b) {

    Punct *punctA = (Punct *)a;
    Punct *punctB = (Punct *)b;

    return (int)(punctA->y - punctB->y);
}

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

double minim(double x, double y)
{
    if (x < y) return x;
    else return y;
}

float modul(float x)
{
    if (x >= 0) return x;
    return -x;
}

double fff(Punct *p, int mij, int st, int dr, double dist)
{
    float dreapta = (float)(p[mij].x + p[mij+1].x) / 2;
    // dreapta - dist, dreapta + dist
    if(modul(dreapta - (float)p[mij].x) > dist || modul((float)p[mij].x - dreapta) > dist)
        return DBL_MAX;

    Punct *ups = (Punct *)malloc(0 * sizeof(Punct));
    int k = 0;
    if(st <= mij && mij <= dr)
        if(modul((float)p[mij].x - dreapta) < dist) {
            ups = realloc(ups, (k + 1) * sizeof(Punct));
            ups[k++] = p[mij];
        }
    if(st <= mij+1 && mij+1 <= dr)
        if(modul((float)p[mij+1].x - dreapta) < dist) {
            ups = realloc(ups, (k + 1) * sizeof(Punct));
            ups[k++] = p[mij + 1];
        }

    if(st <= mij-1 && mij-1 <= dr){
        int i = mij-1;
        while(modul(dreapta - (float)p[i].x) < dist){
            ups = realloc(ups, (k + 1) * sizeof(Punct));
            ups[k++] = p[i--];
            if(st > i || i > dr)
                break;
        }
    }
    if(st <= mij+2 && mij+2 <= dr) {
        int j = mij+2;
        while (modul((float) p[j].x - dreapta) < dist) {
            ups = realloc(ups, (k + 1) * sizeof(Punct));
            ups[k++] = p[j++];
            if (st > j || j > dr)
                break;
        }
    }

    qsort(ups, k, sizeof(Punct), compare_y);
    int a, b;
    for(a = 0; a < k-1; a++)
        for(b = a+1; b <= a+7 && b < k; b++)
            if(a != b && distance(ups[a], ups[b]) < dist)
                dist = distance(ups[a], ups[b]);
    free(ups);
    if(dist == 0)
        puts("Err! dist == 0");
    return dist;
}

double cmap(Punct *p, int st, int dr)
{
    if(dr - st > 2){
        int mij = (st + dr)/2;
        double dist = minim(cmap(p, st, mij), cmap(p, mij+1, dr));
        return minim(dist, fff(p, mij, st, dr, dist));
    }

    int i, j;
    double min_distance = DBL_MAX;
    for(i = st; i <= dr-1; i++)
        for(j = st+1; j <=dr; j++)
            if(i != j && distance(p[i], p[j]) < min_distance)
                min_distance = distance(p[i], p[j]);
    if(min_distance == 0)
        puts("Err! min dist == 0");
    return min_distance;
}

double test(char *fname)
{
    FILE *f;
    f = fopen(fname, "r");
    int n, i;
    fscanf(f, "%d", &n);
    // Crearea vectorului
    Punct *p = (Punct *)malloc(n * sizeof(Punct));
    // Citirea vectorului
    for (i = 0; i < n; i++){
        fscanf(f, "%ld", &p[i].x);
        fscanf(f, "%ld", &p[i].y);
    }

    qsort(p, n, sizeof(Punct), compare_x);
    double r = cmap(p, 0, n-1);
    free(p);
    fclose(f);
    return r;
}

int main()
{
    FILE *fout;
    fout = fopen("cmap.out", "w");
    double rezultat;
    rezultat = test("cmap.in");
    fprintf(fout, "%f", rezultat);
    fclose(fout);

    /*
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test1.txt") - 348638.547165) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test2.txt") - 1510277.801566) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test3.txt") - 84526.067600) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test4.txt") - 4924.201458) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test5.txt") - 67373.170476) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test6.txt") - 21721.562398) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test7.txt") - 6480.748414) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test8.txt") - 14195.229621) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test9.txt") - 7754.601473) < EPS);
    assert(modul(test("/Users/cristinasavin/CLionProjects/untitled1/test10.txt") - 9597.368181) < EPS);

    puts("SUCCES");
    */
    return 0;
}