algorytm dijkstry

0

Witam serdecznie, potrzebuję porady - ponieważ nie wiem czy dobrze zrozumiałem algorytm, a mam do zrobienia program semestralny w oparciu o niego.
Przykładowe miasta( Program ma wczytać je z tekstu, dowolną ilość )
Szczecin Poznan 220
Szczecin Koszalin 110
Poznan Bytom 300
Poznan Lodz 130
Lodz Katowice 170
Bytom Katowice 15
Bytom Wroclaw 180

Na wyjściu po wybraniu któregoś z miast, ma wyskoczyć lista miast, dzięki któremu możemy się tam dostać jak najkrótszą drogą.
Przeczytawszy opracowania tego algorytmu, albo źle go zrozumiałem - albo dobrze zrozumiałem i tak tak go mm interpretować.
W każdym opracowaniu, była mowa o grafie(coś ala "mapa") i na jej podstawie były wyliczane najkrótsze droga z punktu A do D.
Więc mógłby mi ktoś proszę powiedzieć, czy program mam pisać jakoś o oparciu o ten graf, chociaż o ile jestem w stanie sobie wyobrazić napisanie go, mając gotowy już graf, tak nie jestem juz w stanie tego pojąc, jak go napisać mając o wiele więcej miast.

Z góry dziękuję za pomoc.

Pozdrawiam
Wesołych świąt :)

0

Nie bardzo cię rozumiem. Wybranie jednego miasta to chyba trochę mało? Może jednak wybierasz dwa miasta między którymi wyznaczasz trasę? Tak czy siak algorytm Dijkstry zwraca ci najkrótsze odległości od wybranego wierzchołka (miasta) do wszystkich pozostałych. A twojego drugiego pytania w ogóle nie rozumiem. Każde miasto to wierzchołek grafu, każda para podana na wejściu to krawędź a odleglość to waga tej krawędzi.

Podsumowując: gdzie jest problem?

0

Na wstępie wprowadzam dowolną ilość dwóch miast, podając między nimi odległość. Po wklepaniu miast(bądź wczytaniu z pliku) podaje jedno miasto i program ma wyświetlić najkrótszą odległość, do każdego miasta, jeżeli jest taka mozliwość.
Tak wygląda treść całego semestralnego zadania: http://screenshooter.net/101726245/nyvcwun
Tak jak wspomniałem, zrozumiałem algorytm, ale nie rozumiem jak mam go użyć w oparciu o mój program, więc to jest mój główny problem - bo nie wiem po prostu czy dobrze zrozumiałem ten algorytm.

Dzięki za odpowiedź : )

3

Zadanie semestralne? Serio? o_O Nie żeby coś, ale my dostawaliśmy takie zadania do stuknięcia w 30 min na kolokwium na 2 semestrze studiów...
Tak czy siak, napisałem już wyżej jak należy to zrobić.

  • czytasz z wejścia dane i tworzysz sobie z nich graf
  • wczytujesz miasto źrodłowe
  • odpalasz Dijsktrę (w trakcie relaksacji wierzchołka oczywiście oprócz aktualnie minimalnej sumy wag na dojście do tego wierzchołka zapisujesz także informacje o tym skąd tam przyszedłeś, tzn jaki jest poprzedni wierzchołek na ścieżce)
  • wypisujesz ścieżki uzyskane w Dijkstrze zwyczajnie idąc sobie od końca, tzn dla każdego wierzchołka który nie jest źródłem odczytujesz sobie informacje o "poprzednim" wierzchołki (tą którą zapisaliśmy sobie wyżej) i tak aż trafisz na źródło
    Na oko to jest 20 min pisania, 30 jeśli nie znasz Dijkstry i musisz doczytać na wikipedii jak implementować.
0

No właśnie jedyny problem będę mieć z "czytasz z wejścia dane i tworzysz sobie z nich graf" Z resztą sobie poradzę, tylko czy mógłbyś odnieść się z jakąś wskazówką konkretnie do tego podpunktu?
Dzieki za pomoc :)

1

Przecież już to napisałem o_O
Wczytujesz dane z wejścia. Każde wczytane miasto to wierzchołek grafu. Każda wczytana z wejścia linijka w postaci
Miasto1 Miasto2 Odległość
to krawędź ''Miasto1-Miasto2 o wadze Odległość"
Więc czytasz sobie po linijce i po każdej wczytanej linijce wrzucasz sobie podane Miasta do zbioru wierzchołków a parę razem z wagą to zbioru krawędzi.
Graf składa sie z wierzchołków i krawędzi. Co jeszcze ci tu potrzebne?

0

Nic, teraz zrozumiałem :)
Dzięki

0

Witam,
jeżeli mogę jeszczę tylko zapytać o jedną podpowiedź, to wczytywanie tych miast wraz z odległością najlepiej będzie zrobić listą jednokierunkową? Od wczoraj przeszukuje internet i głowię się jak zrobić to najłatwiej i najbardziej ekonomicznie.
Chyba, że przez wczytywanie tych miast i odległości z pliku należy to zrobić inaczej?
Z góry dziękuję za odpowiedź.
Pozdrawiam

1

Nie, wczytanie zrobić scanf'em w pętli.

0

Przyznam, że takiej odpowiedzi się nie spodziewałem i zbiłeś mnie całkowicie z tropu. Czyli nie muszę tutaj z niczym kombinować, po prostu utworzyć trzy tablice? Jedna odpowiadająca za miasto1,druga za miasto2 i trzecia za odległość?
Przepraszam, jeżeli moje pytania są zbyt banalne i zawracają tyłko niepotrzebnie głowe :)

1

poczytaj o strukturach i listach nawlekanych.

1

Nie nie nie. @_13th_Dragon czytaj uważnie, on pyta o reprezentacje grafu, tylko nie umie tego sensownie nazwać ;)
@ZłotyKot lekcja na dziś:
http://en.wikipedia.org/wiki/Graph_(abstract_data_type)#Representations
http://pl.wikipedia.org/wiki/Reprezentacja_grafu
Generalnie istnieją 3 główne reprezentacje. Należy brać pod uwagę że różne algorytmy łatwiej/trudniej napisać w oparciu o daną reprezentację. Dijkstre / Bellmana Forda, które cię interesują najprościej będzie stuknąć w oparciu o macierz sąsiedztwa VxV albo o listę sąsiedztwa. Jasne że można też w oparciu o macierz incydencji, ale byłoby to mniej wygodne.

2

@Shalom i właśnie do reprezentacji poradziłem mu nad czym musi się zastanowić.
Co do macierzy sąsiedztwa lub listy sąsiedztwa to powiedz mi jakim cudem przy takich reprezentacjach zamierzasz osiągnąć typowej dla Dijkstry O(V2) ?
W C o ile wczytujesz listę sąsiedztwa bez wcześniejszego podania ilości węzłów (i nie martwimy się kwadratowym kosztem wczytywania) lepsza będzie następująca reprezentacja:

struct node;
typedef struct edge
  {
   struct node *to;
   struct edge *next;
   double price;
  } Edge;
typedef struct node
  {
   char *name;
   double distance;
   struct node *from,*queue,*next;
   struct edge *head;
  } Node;
typedef struct graph
  {
   struct node *queue,*head;
  } Graph;
0

Cześć, to znowu ja. Udało mi się napisać wczytywanie z pliku oraz zrobienie macierzy sąsiedztwa - jednakże teraz mam problem z użyciem algorytm DIJKSTRY, nie wiem jak się dobrać do niego, poprzez użycie macierzy sąsiedztwa.
Byłbym zobowiązany, za jakąkolwiek radę

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#define MAX 100 
struct  graf 
{ 
   int city1; 
   int city2; 
   int dist; // distance    
}; 

main() 
{ 
   int wmax=0; 
   struct graf Graf[50]; 
FILE *plik = fopen("karol.txt", "r"); 
for(int i=0;i<2;i++) 
{ 

   fscanf(plik, "%d", &Graf[i].city1); 
   fscanf(plik, "%d", &Graf[i].city2); 
   fscanf(plik, "%d", &Graf[i].dist); 
} 

for(int i=0;i<2;i++) 
{ 
   printf("%d ",Graf[i].city1); 
   printf("%d ",Graf[i].city2); 
   printf("%d ",Graf[i].dist); 
   printf("\n"); 
} 
char matrix[MAX][MAX]; //macierz sąsiedztwa 
int  distance[MAX][MAX]; // macierz wag 

for(int i=0;i<MAX;i++) { 
for(int j=0;j<MAX;j++){ 
matrix[i][j]=0;    
distance[i][j]=0;    
}   } 
 for(int k = 0; k < 2; k++) 
 {    
  
if(Graf[k].city1> wmax) 
{ 
   wmax=Graf[k].city1; 
} 
else 
{ 
   wmax=wmax; 
} 
if(Graf[k].city2> wmax) 
{ 
   wmax=Graf[k].city2; 
} 
else 
{ 
   wmax=wmax; 
} 
matrix[Graf[k].city1-1][Graf[k].city2-1] = 1; 
distance[(Graf[k].city1)-1][(Graf[k].city2)-1]=Graf[k].dist; 
} 
 for(int i = 0; i < wmax; i++) 
  { 
    for(int j = 0; j < wmax; j++) 
    { 
    
   printf("%d  ",distance[i][j]); 
    
     } 
     printf("\n"); 
} 


} 
 

EDIT: Dopiero po napisaniu tego postu, zauważyłem drugą stronę :| Więc, jeżeli dobrze zrozumiałem - to obecnie ten program nic mi nie daje, bo nie mogę użyć macierzy sąsiedztwa? Troszkę się pogubiłem. PS: Projekt narzuca mi algorytm Dijkstry'ego :.

1

Serio? WTF? Pierwszy link z google
http://www.geeksforgeeks.org/greedy-algorithms-set-6-dijkstras-shortest-path-algorithm/
Z takimi umiejetnościami szukania w internecie to uciekaj z tych swoich studiów, im szybciej tym lepiej...

1

@ZłotyKot, weź zrób wczytanie do struktur jak pokazałem wyżej.
Wtedy cały algorytm Dijkstry zapiszesz w 5 wierszy.

0

@Shalom masz rację, mogłem jeszcze poszukać na internecie, ale gdy na początku nie mogłem znaleźć żadnego,przydatnego dla mnie programu w C to zrezygnowałem, więc teraz w pierwszym momencie nawet o tym nie pomyślałem.
@_13th_Dragon z chęcią, bym to zrobił, ale niestety nie mam żadnego pojęcia jak to zrobić, więc próbowałem przerobić mój program z użyciem tego wyżej, który nadesłał mi Shalom.
Ogólnie moja koncepcja wygląda,tak aby na razie zrobić ten program, aby działał, a potem go "udoskonalić" zagłębić się w niego, w pełni zrozumieć.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>

#define MAX 100
#define V 2
struct  graf
{
	int city1;
	int city2;
	int dist; // distance	
};
int minDistance(int dist[], bool sptSet[])
{
   int min = INT_MAX, min_index;
 
   for (int v = 0; v < V; v++)
     if (sptSet[v] == false && dist[v] <= min)
         min = dist[v], min_index = v;
 
   return min_index;
}
int printSolution(int dist[], int n)
{
   printf("Vertex   Distance from Source\n");
   for (int i = 0; i < V; i++)
      printf("%d \t\t %d\n", i, dist[i]);
}
void dijkstra(int graph[V][V], int src)
{
     int dist[V];     
     bool sptSet[V]; 
     for (int i = 0; i < V; i++)
        dist[i] = INT_MAX, sptSet[i] = false;
 
     dist[src] = 0;
 
     for (int count = 0; count < V-1; count++)
     {
       
       int u = minDistance(dist, sptSet);
 
       sptSet[u] = true;
 
       for (int v = 0; v < V; v++)
 
         
         if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX 
                                       && dist[u]+graph[u][v] < dist[v])
            dist[v] = dist[u] + graph[u][v];
     }
 printSolution(dist, V);
}

 
 
main()
{
	
	int wmax=0;
	struct graf Graf[50];
FILE *plik = fopen("karol.txt", "r");
for(int i=0;i<2;i++)
{

	fscanf(plik, "%d", &Graf[i].city1);
	fscanf(plik, "%d", &Graf[i].city2);
	fscanf(plik, "%d", &Graf[i].dist);
}

for(int i=0;i<2;i++)
{
	printf("%d ",Graf[i].city1);
	printf("%d ",Graf[i].city2);
	printf("%d ",Graf[i].dist);
	printf("\n");
}
char matrix[MAX][MAX]; //macierz sąsiedztwa
int  distance[MAX][MAX]; // macierz wag

for(int i=0;i<MAX;i++) {
for(int j=0;j<MAX;j++){
matrix[i][j]=0;	
distance[i][j]=0;	
}	} 
 for(int k = 0; k < 2; k++)
 {	
 
if(Graf[k].city1> wmax)
{
	wmax=Graf[k].city1;
}
else
{
	wmax=wmax;
}
if(Graf[k].city2> wmax)
{
	wmax=Graf[k].city2;
}
else
{
	wmax=wmax;
}
matrix[Graf[k].city1-1][Graf[k].city2-1] = 1;
distance[(Graf[k].city1)-1][(Graf[k].city2)-1]=Graf[k].dist;
}

	printf("%d  ",dijkstra(distance,0);
	
	


}

Po uruchomieniu programu, wywala taki błąd:
Błąd jaki wywala : cannot convert 'int ()[100]' to 'int ()[2]' for argument '1' to 'void dijkstra(int (*)[2], int)'

Z góry dziękuję, za ponowną pomoc i przepraszam, jeżeli to jakieś upierdliwe pytanie, lub co gorsza jakiś kardynalny błąd : )

1
ZłotyKot napisał(a):

Ogólnie moja koncepcja wygląda,tak aby na razie zrobić ten program, aby działał, a potem go "udoskonalić" zagłębić się w niego, w pełni zrozumieć.
Jest to bardzo znana koncepcja pochodząca z kawału:
W pewnym wariatkowie zbudowano basen ze skocznią.
Na uroczystym otwarciu dyrektor mówi: - Jak nauczycie się skakać to nalejemy wodę.

0

Pewnie masz rację.
Pokombinuję dzisiaj nad tym : )

1 użytkowników online, w tym zalogowanych: 0, gości: 1