Advertisement
dadiw96

Pojebane Cytrynki z Spoja

Jan 10th, 2017
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.89 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. // http://pl.spoj.com/problems/LEMONS/ na algorytmie Dijkstry
  6. //----------------struktury---------------------
  7.  
  8. struct Point
  9. {
  10.     int x, y;
  11. } point;                //struktura przechowujaca punkt,
  12.  
  13. struct Edge
  14. {
  15.     int from;
  16.     int to;
  17.     int length;
  18. } edge;                 //struktura przechowujaca wezel
  19.  
  20.  
  21. //----------------metody---------------------
  22.  
  23. void loadFile();                                        //funkcja wczytujaca zawartosc pliku
  24. int getDistance(struct Point, struct Point b);          //funkcja obliczajaca odleglosc miedzy dwoma punktami
  25. int comparator(const void *p, const void *q);           //funkcja okreslajaca wartosc porownania dla
  26.                                                         //algorytmu quickSort, przy sortowaniu struktur Edge
  27. void fillAllEdgesTable();                               //funkcja wypelniajaca tablice ze wszystkimi krawedziami
  28.  
  29. int checkDidExistConnectionBetweenNodes(struct Edge* list, int counter, int from, int to);      //utworzenie grafu na podstawie krawedzi wezlow
  30.                                                                                                 //i sprawdzenie czy istnieje sciezka miedzy a i b
  31. void printEdgeTable(struct Edge *list, int counter);    //funkcja pomocnicza, opcjonalna - wydruk tablicy
  32. void DFS(int i);
  33. //----------------zmienne---------------------
  34. //*p to to samo co p[]
  35. //**p to to samo co p[][]
  36. //robimy tak, bo nie mozemy zrobic p = int[zmienna], mozemy tylko stalych wartosci uzywac np. p = int[5], w innym przypadku musimy uzywac alokowania
  37. //na tablice za pomoca funkcji malloc
  38.  
  39. struct Point *p;                //tablica przechowujaca punkty
  40. struct Edge *edges;             //tablica przechowujaca wszystkie krawedzie sciezki miedzy punktami
  41. struct Edge *resultEdgeTree;    //tablica przechowujaca krawedzie wynikowego drzwa spinajacego
  42.  
  43. int size;                       //ilosc punktow
  44. int allEdgesCounter;            //ilosc wszystkich krawedzi
  45. int spanningTreeEdgeSize;       //ilosc krawedzi wynikowego drzewa spinajacego
  46.  
  47. //DFS
  48. int** x;                        //tymczasowe drzewo (macierz sasiedztwa) utworzona na podstawie aktualnie wybranych krawedzi
  49. int *visited;                   //lista odwiedzonych wierzcholkow w X
  50. int searched;                   //wierzcholek do ktorego sprawdzamy czy istnieje polaczenie
  51. int finded;                     //wynik wyszukiwania sciezki
  52.  
  53. int main(){
  54.     loadFile();             //wczytyujemy wartosci z pliku i wypelniamy tablice points
  55.     fillAllEdgesTable();    //wypelniamy tablice edges bazujac na tablicy points
  56.  
  57.     //http://www.geeksforgeeks.org/comparator-function-of-qsort-in-c/
  58.     //sortowanie tablicy wg. regul opisanych w metodzie comparator(porówmując) sortujemy tablice z krawedziami wg. ich dlugosci
  59.    
  60.     qsort((void*)edges, allEdgesCounter, sizeof(edges[0]), comparator);     //sortuje z funkcji bibliotecznej
  61.     //mamy posortowana tablice ze wszystkimi krwedziami w grafie, teraz probujemy je dodawac do tablicy
  62.     //z krawiedziami wynikowymi, jesli nowo dodawana krawedz powoduje powstanie cyklu (sciezka z a->b juz istnieje, pomijamy);
  63.     int i;                              //licznik petli
  64.     int actualResultCounter = 0;        //licznik aktualnie dodanych wezlow do tablicy wynikowej programu
  65.    
  66.     for(i=0;i<allEdgesCounter;i++){         //iterujemy (przechodzimy) po wszystkich krawedziach
  67.    
  68.         int exist = checkDidExistConnectionBetweenNodes(resultEdgeTree, actualResultCounter, edges[i].from, edges[i].to);   //Na podstawie zawartosci tabeli wyiników jest tworzony graf
  69.         if(exist == 0){                                                                                                     //sprawdzamy czy w grafie istnieje polaczenie miedzy wezlami badanej krawedzi
  70.             resultEdgeTree[actualResultCounter] = edges[i];     //jesli nie, dodajemy do zbioru krawedzi wynikowych badana krawedz
  71.             actualResultCounter++; 
  72.         }
  73.     }
  74.    
  75.     int sum = 0;
  76.     for(i=0;i<spanningTreeEdgeSize;i++){
  77.         sum+=resultEdgeTree[i].length;
  78.     }
  79.    
  80.     printEdgeTable(resultEdgeTree, spanningTreeEdgeSize);
  81.  
  82.     printf("SUMA: %d",sum);
  83.     //sumujemy wartosci podajemy wynik
  84.    
  85.     return 1;
  86. }
  87.  
  88. void fillAllEdgesTable(){
  89.     int i, j, nodeCounter = 0;      //deklaracja
  90.     //tworzymy polaczenie miedzy dowolnymi dwoma wierzcholkami (punktami) i dodajemy do tablicy addEdgesCounter,  
  91.     for(i = 0 ; i < size ; i++){
  92.         //porownujemy tylko z elemenentami nastepujacymi po porownywanym, poniewaz odleglosc a -> b jest taka sama jak b -> a
  93.         for(j= i+1; j < size; j++){
  94.             //dodanie krawedzi do tablicy wszystkich krawedzi (edges)
  95.             edges[nodeCounter].from = i;
  96.             edges[nodeCounter].to = j;
  97.             edges[nodeCounter].length = getDistance(p[i],p[j]);
  98.             nodeCounter++;
  99.         }
  100.     }
  101. }
  102.  
  103. //utworzenie grafu na podstawie krawedzi wezlow i sprawdzenie czy istnieje sciezka miedzy a i b
  104. int checkDidExistConnectionBetweenNodes(struct Edge* list, int counter, int from, int to){
  105.     //tablica dwuwymiarowa (baba w babie)
  106.     //mamy tabele o rozmiarze counter * counter - macierz sasiedztwa
  107.    
  108.     //zadeklarowanie "zewnetrznej tablicy"
  109.     x = malloc(size * sizeof(int*));
  110.  
  111.     //ilosc elementow w liscie
  112.     //parametr wejsciowy counter
  113.  
  114.     int i,j;
  115.     for (i = 0; i < size; i++) {   
  116.         x[i] = malloc(size * sizeof(int));  //zaalokowanie pamieci dla "wewnetrznej" tablicy
  117.     }      
  118.    
  119.     for(i=0; i<size; i++){
  120.         for(j=0;j<size; j++){
  121.             x[i][j] = 0;    //czyszczenie tablicy, wypelnienie zerami
  122.         }
  123.     }
  124.    
  125.     //wypelnienie tabeli krawedziami
  126.     //counter jest nam potrzebny w celu ograniczenia przeglądanych elementow tablicy , np. ma ona przeznaczone miejsce na 9 krawedzi (tyle bedzie koncowo) ale aktualnie jest tam tylko jedna,
  127.     //w tym przypadku do macierzy sasiedztwa dodajemy tylko ten pierwszy element
  128.     for(i=0; i<counter;i++){
  129.         x[list[i].from][list[i].to] = 1;
  130.         x[list[i].to][list[i].from] = 1;
  131.     }
  132.  
  133.     visited = malloc(size * sizeof(int));   //DFS - tablica zawierajaca odwiedzone przez algorytm wierzcholki, alokacja miejsca
  134.    
  135.     for(i=0;i<size;i++){
  136.         visited[i] = 0;                     //wyzerowanie tablicy odwiedzonych wierzcholkow
  137.     }
  138.  
  139.     DFS(from);                              //wywolanie algorytmu rekurencyjnego DFS z poczatkiem w wierzcholku FROM
  140.     if(visited[to]==1){
  141.         return 1;
  142.     } else {
  143.         return 0;
  144.     }
  145. }
  146.  
  147. //algorytm wyszukiwania DFS
  148. void DFS(int i)
  149. {
  150.     int j;
  151.     visited[i]=1;
  152.    
  153.     for(j=0;j<size;j++){
  154.        if(!visited[j] &&x [i][j] == 1){
  155.             DFS(j);
  156.        }
  157.     }
  158.  
  159. }
  160.  
  161. //funkcja pomocnicza, opcjonalna - wydruk tablicy intow(długości krawędzi)
  162. void printIntTable(int ** list, int counter){
  163.     int i,j;
  164.     for(i=0; i<counter; i++){
  165.         for(j=0;j<counter;j++){
  166.             printf("%d ", list[i][j]);
  167.         }
  168.         printf("\n");
  169.     }
  170. }
  171.  
  172. //funkcja pomocnicza, opcjonalna - wydruk tablicy krawedzi
  173. //*list --> list[]
  174. void printEdgeTable(struct Edge *list, int counter){
  175.     int i;
  176.     printf("Printing table elements\n");
  177.     for(i=0; i<counter;i++){
  178.         printf("\t%d. from: %d, to: %d,  length: %d\n", i, list[i].from, list[i].to, list[i].length);
  179.     }
  180. }
  181.  
  182. //wczytywanie z pliku
  183. void loadFile(){
  184.    
  185.     //plik z ktorego czytamy
  186.     const char* fileName = "Dane.txt";
  187.     //otwarcie pliku w trybie odczytu
  188.     FILE* file = fopen(fileName, "r");
  189.     //bufor, zakladamy ze linia ma nie wiecej niz 256 znakow
  190.     char line[256];
  191.     //zmienne do ktorych wczytamy wspolrzedne punktow
  192.     int x, y;
  193.     //licznik(counter) przeczytanych punktów -1 linia
  194.     int counter = -1;
  195.     //tak dlugo jak mamy co czytac
  196.     while (fgets(line, sizeof(line), file)) {
  197.         //pobieranie za pomoca wzorca wartosci x,y z pobranej linii
  198.         sscanf(line,"%d %d",&x,&y);
  199.         //counter == -1, zeby nie brac pod uwage przy umieszczaniu w tablicy pierwszej linijki
  200.         if(counter == -1){
  201.             //jesli pierwsza linia, ilosc pkt
  202.             counter = 0;
  203.             //podglad pierwszej linijki 10
  204.             size = x;
  205.             //inicjalizacja tablicy struct Point[size] w ktorej beda wspolrzedne punktow ;
  206.             p = malloc(sizeof(struct Point)*size);  //funkcja malloc rezerwuje ilosc pamieci na tablice,
  207.                                                     //przykladowo dla size = 5, wywolanie malloc(sizeof(Struct Point)*size) da taki sam efekt jak p = struct Point[5];
  208.         } else { //inna linijka niz pierwsza dodanie do kolejnych indeksow tablicy wspolrzednych pkt x,y (uzupełnienie tabeli)
  209.             p[counter].x = x;   //do elementow struktury odwolujemy sie przez kropke
  210.             p[counter].y = y;
  211.             //zwiekszenie licznika po dodaniu
  212.             counter++;
  213.         }
  214.     }
  215.     allEdgesCounter = size*(size-1)/2;          //ze wzoru na ilosc krawedzi w grafie: n*(n-1)/2
  216.     spanningTreeEdgeSize = size - 1;            //ilosc krawedzi bedzie rowna ilosci wierzcholkow -1, gdyby byla rowna, mielibysmy obiekt zamkniety
  217.     edges = malloc(sizeof (struct Edge)* (allEdgesCounter));        //rezerwowanie miejsca dla tablicy wynikow
  218.     resultEdgeTree = malloc(sizeof (struct Edge) * (size - 1));     //deklaracja tablicy wynikowej
  219.     fclose(file);
  220. }
  221.  
  222. int getDistance(struct Point a, struct Point b)
  223. {
  224.     //wynik dzialania funkcji
  225.     int distance;
  226.     distance = (int)(sqrt((a.x - b.x) * (a.x - b.x) + (a.y-b.y) *(a.y-b.y)));
  227.     return distance;
  228. }
  229.  
  230. //funkcja sortujaca
  231. int comparator(const void *p, const void *q)
  232. {
  233.     int l = ((struct Edge *)p)->length; //przez --> zamiast . bo uzywamy wskaznika na strukture a nie "obiektu" struktury
  234.     int r = ((struct Edge *)q)->length;
  235.     return (l - r);
  236. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement