155 lines
5.0 KiB
C++
155 lines
5.0 KiB
C++
|
|
/***
|
|
* 13. Kurier ma za zadanie zawieść towar do klientów w różnych lokalizacjach i powrócić do miejsca, z którego wyjechał. Kurier musi odwiedzić każdego klienta raz i tylko raz. Należy
|
|
znaleźć zamkniętą najkrótszą drogę, która umożliwia odwiedzenie wszystkich klientów.
|
|
W pliku wejściowym zapisane są długości dróg pomiędzy miastami. Drogi zapisane
|
|
są w następujący sposób:
|
|
(<klient A> - <klient B> : <odległość>).
|
|
Niektóre drogi nie są symetryczne, tzn. jest pewna różnica między drogą tam a z powrotem.
|
|
Zapis (<klient C> -> <klient D> : <odległość CD>), oznacza długość drogi jednokierunkowej
|
|
od klienta C do klienta D. Poszczególne drogi są rozdzielone przecinkami. Nie jest podana
|
|
liczba dróg. Jeżeli nie jest możliwe wyznaczenie drogi, program zgłasza odpowiedni
|
|
komunikat. Przykładowy plik wejściowy:
|
|
(1 - 2 : 4.5), (4 -> 3 : 4.5), (4 - 2 : 0.4)
|
|
W pliku wynikowym należy zapisać drogę kuriera (kolejność odwiedzania klientów i długość
|
|
drogi).
|
|
Program uruchamiany jest z linii poleceń z potrzebnymi przełącznikami, natomiast
|
|
uruchomienie programu bez parametrów powoduje wypisanie krótkiej instrukcji
|
|
|
|
1 2 3 4
|
|
1 4.5
|
|
|
|
2 4.5 0.4
|
|
|
|
3 4.5
|
|
|
|
4 0.4
|
|
|
|
**/
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <string>
|
|
#include "include/cxxopts.hpp"
|
|
#include "include/types.hpp"
|
|
#include <algorithm>
|
|
#include <limits.h>
|
|
#include <queue>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
double nieskończoność=std::numeric_limits<double>::max();
|
|
|
|
using namespace std;
|
|
|
|
cxxopts::Options options("Kurier", "Program rozwiązujący problem kuriera");
|
|
|
|
/*
|
|
*
|
|
* Parsujemy A, B, rodzaj korelacji <bool>, dystans
|
|
*
|
|
*
|
|
*/
|
|
typedef std::map<std::string, std::map<std::string, double>> mapa;
|
|
mapa mapaOdległości;
|
|
/*
|
|
* @brief Funkcja czyszcząca stringi z niepotrzebnych znaków
|
|
*/
|
|
void czyscStringa( string &str, char* znakiDoCzyszczenia ) {
|
|
for ( unsigned int i = 0; i < strlen(znakiDoCzyszczenia); ++i ) {
|
|
str.erase( remove(str.begin(), str.end(), znakiDoCzyszczenia[i]), str.end() );
|
|
}
|
|
}
|
|
|
|
|
|
void dijkstruj(mapa doDijkstrnięcia){
|
|
for(auto miasto : doDijkstrnięcia)
|
|
{
|
|
// doDijkstrnięcia.rbegin()
|
|
}
|
|
}
|
|
|
|
void dumpOutput(string outputFile, string preparedString)
|
|
{
|
|
ofstream file(outputFile);
|
|
file << preparedString;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Funkcja parsująca dane wejściowe.
|
|
*
|
|
* @details Funkcja pobiera dane wejściowe z przekazanej ścieżki do pliku. Plik zawiera długości dróg pomiędzy poszczególnymi miastami w formacie (<klient A> - <klient B> : <odległość>).
|
|
*
|
|
* @param inputFile Ścieżka do pliku wejściowego
|
|
*
|
|
* @return iterator pliku
|
|
*/
|
|
void parseInput(string inputFile) {
|
|
ifstream file(inputFile);
|
|
std::string token,miastoA,miastoB,dystans,rodzajRelacji;
|
|
while(std::getline(file, token, ',')) {
|
|
czyscStringa(token, "(:)");
|
|
istringstream tokenstream(token);
|
|
tokenstream >> miastoA >> rodzajRelacji >> miastoB >> dystans;
|
|
if (rodzajRelacji.compare("-")==0) {
|
|
// Jeśli drugie miasto zaczyna się od znaku '-', to znaczy, że jest to droga dwukierunkowa.
|
|
// Dodajemy odległość do mapy dla obu kierunków.
|
|
mapaOdległości[miastoA][miastoB] = stod(dystans);
|
|
mapaOdległości[miastoB][miastoA] = stod(dystans);
|
|
} else if (rodzajRelacji.compare("->")==0) {
|
|
// Jeśli drugie miasto zaczyna się od znaku '>', to znaczy, że jest to droga jednokierunkowa.
|
|
// Dodajemy odległość tylko w jednym kierunku.
|
|
mapaOdległości[miastoA][miastoB] = stod(dystans);
|
|
mapaOdległości[miastoB][miastoA] = nieskończoność;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* @brief Główna funkcja.
|
|
*
|
|
*/
|
|
int main (int argc, char *argv[])
|
|
{
|
|
|
|
options.add_options()
|
|
("d,debug", "Włącza tryb debugowania") // a bool parameter
|
|
("h,help", "Pokazuje pomoc") // a bool parameter
|
|
("i,input", "Nazwa pliku wejściowego", cxxopts::value<string>())
|
|
("o,output", "Nazwa pliku wyjściowego", cxxopts::value<string>())
|
|
("v,verbose", "Pokazuje tok działania programu", cxxopts::value<bool>()->default_value("false"));
|
|
|
|
auto result = options.parse(argc, argv);
|
|
|
|
// Jeżeli przełącznik -h jest ustawiony albo nie podano argumetów, wyświetla pomoc.
|
|
if (result.count("help") || argc == 1) {
|
|
std::cout << options.help() << std::endl;
|
|
exit(0);
|
|
}
|
|
bool debug = result["debug"].as<bool>();
|
|
string plikWejsciowy;
|
|
string plikWyjsciowy;
|
|
if (result.count("input") && result.count("output")) {
|
|
plikWejsciowy = result["input"].as<string>();
|
|
parseInput(plikWejsciowy);
|
|
dijkstruj(mapaOdległości);
|
|
plikWyjsciowy = result["output"].as<string>();
|
|
|
|
} else {
|
|
std::cout << std::endl << "Błąd - nie podano wymaganych parametrów" << std::endl << std::endl << std::endl << options.help() << std::endl;
|
|
exit(3);
|
|
}
|
|
if (debug == true) {
|
|
for (int i = 0; i < argc; i++) {
|
|
std::cout << argv[i] << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
exit(0);
|
|
}
|