Advertisement
Guest User

Acceler8

a guest
Mar 8th, 2013
825
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 41.81 KB | None | 0 0
  1. /*!
  2.  * \file main.cpp
  3.  * \brief This file contains source code that solves the Work Hard - Play Hard problem for the Acceler8 contest
  4.  */
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include <time.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <sys/mman.h>
  11. #include <sys/time.h>
  12. #include <omp.h>
  13.  
  14. #include <iostream>
  15. #include <fstream>
  16. #include <string>
  17. #include <vector>
  18. #include <list>
  19. #include <set>
  20. #include <map>
  21. #include <queue>
  22. #include <iterator>
  23. #include <algorithm>
  24. #include <unordered_map>
  25. #include <unordered_set>
  26. #include <istream>
  27. #include <streambuf>
  28.  
  29. using namespace std;
  30.  
  31.  
  32. const double EPS = 1e-9;
  33. const int INT_INF = 2000000000;
  34. const int TYPES = 5;
  35. const float FLOAT_INF = 1e100;
  36.  
  37. typedef unsigned long ulong;
  38. typedef char* cstr;
  39.  
  40. struct Flight {
  41.         int id;
  42.         int from;
  43.         int to;
  44.         int company;
  45.         ulong take_off_time;/*!< Take off time (epoch). */
  46.         ulong land_time;/*!< Land time (epoch). */
  47.         float cost;/*!< The cost of the flight. */
  48.         float discount;/*!< The discount applied to the cost. */
  49. };
  50.  
  51.  
  52.  
  53. class File {
  54.         struct membuf: streambuf {
  55.                 membuf(cstr begin, cstr end) {
  56.                         this->setg(begin, begin, end);
  57.                 }
  58.         };
  59.  
  60.         cstr filename;
  61.         size_t size;
  62.         int descriptor;
  63.         cstr mapped;
  64.         size_t buffer_size;
  65.         cstr buffer;
  66.         size_t buffer_ptr;
  67.         membuf *sbuf;
  68.  
  69. public:
  70.         File(cstr filename) :
  71.                 filename(filename), buffer_ptr(0) {
  72.         }
  73.  
  74.         void fopen() {
  75.                 descriptor = open(filename, O_RDONLY);
  76.                 size = lseek(descriptor, 0, SEEK_END);
  77.  
  78.                 if (size == 0) {
  79.                         mapped = new char[0];
  80.                 } else {
  81.                         mapped = (cstr) mmap(0, size, PROT_READ, MAP_SHARED, descriptor, 0);
  82.                         if (mapped == MAP_FAILED) {
  83.                                 cerr << "Problem while opening the file " << filename << endl;
  84.                                 exit(0);
  85.                         }
  86.                 }
  87.  
  88.                 buffer_size = size + 1;
  89.                 buffer = new char[buffer_size];
  90.                 memset(buffer, 0, buffer_size);
  91.                 sbuf = new membuf(mapped, mapped + size);
  92.         }
  93.  
  94.         membuf* get_mapped_buf() {
  95.                 return sbuf;
  96.         }
  97.  
  98.         void fclose() {
  99.                 if (size != 0) {
  100.                         munmap(mapped, size);
  101.                 }
  102.                 close(descriptor);
  103.                 delete sbuf;
  104.         }
  105.  
  106.         void dispose() {
  107.                 delete[] buffer;
  108.         }
  109.  
  110.         cstr read_line(istream& input) {
  111.                 cstr begin = buffer + buffer_ptr;
  112.                 input.getline(begin, buffer_size - buffer_ptr);
  113.                 buffer_ptr += strlen(begin) + 1;
  114.                 return begin;
  115.         }
  116. };
  117.  
  118.  
  119. struct Parameters {
  120.         cstr from;/*!< The city where the travel begins */
  121.         cstr to;/*!< The city where the conference takes place */
  122.         ulong dep_time_min;/*!< The minimum departure time for the conference (epoch). No flight towards the conference's city must be scheduled before this time. */
  123.         ulong dep_time_max;/*!< The maximum departure time for the conference (epoch). No flight towards the conference's city must be scheduled after this time.  */
  124.         ulong ar_time_min;/*!< The minimum arrival time after the conference (epoch). No flight from the conference's city must be scheduled before this time.  */
  125.         ulong ar_time_max;/*!< The maximum arrival time after the conference (epoch). No flight from the conference's city must be scheduled after this time.  */
  126.         ulong max_layover_time;/*!< You don't want to wait more than this amount of time at the airport between 2 flights (in seconds) */
  127.         ulong vacation_time_min;/*!< Your minimum vacation time (in seconds). You can't be in a plane during this time. */
  128.         ulong vacation_time_max;/*!< Your maximum vacation time (in seconds). You can't be in a plane during this time. */
  129.         vector<cstr> airports_of_interest;/*!< The list of cities you are interested in. */
  130.         cstr flights_file;/*!< The name of the file containing the flights. */
  131.         cstr alliances_file;/*!< The name of the file containing the company alliances. */
  132.         cstr work_hard_file;/*!< The file used to output the work hard result. */
  133.         cstr play_hard_file;/*!< The file used to output the play hard result. */
  134.         int nb_threads;/*!< The maximum number of worker threads */
  135. };
  136.  
  137.  
  138. class cstr_hash {
  139. public:
  140.         long operator()(const cstr &str) const {
  141.                 long result = 0;
  142.                 cstr a = str;
  143.                 while (*a != 0) {
  144.                         result = (result << 8) + result + (*a);
  145.                         ++a;
  146.                 }
  147.                 return result;
  148.         }
  149. };
  150.  
  151. class cstr_comparator {
  152. public:
  153.         bool operator()(const cstr &s1, const cstr &s2) const {
  154.                 return strcmp(s1, s2) == 0;
  155.         }
  156. };
  157.  
  158. unordered_set<cstr, cstr_hash, cstr_comparator> string_pool;
  159.  
  160.  
  161. typedef pair<float, int> fPair;
  162. typedef pair<double, int> dPair;
  163. typedef vector<vector<fPair> > Graph;
  164. typedef vector<Flight> Travel;
  165. typedef unordered_map<cstr, int> umap;
  166.  
  167. enum {
  168.         FROM_ANY = 0,
  169.         FROM_THIS = 1,
  170.         FIRST_THIS = 2,
  171.         FROM_ALLIANCE = 3,
  172.         FIRST_ALLIANCE = 4
  173. };
  174.  
  175. int id_counter = 0;
  176. int city_counter = 0;
  177. int company_counter = 0;
  178.  
  179. umap id_by_string;
  180. umap city_by_string;
  181. umap company_by_string;
  182.  
  183. vector<cstr> id_by_index;
  184. vector<cstr> city_by_index;
  185. vector<cstr> company_by_index;
  186.  
  187. Graph home_vacation_conference_graph;
  188. Graph home_conference_vacation_graph;
  189.  
  190. vector<int> home_vacation_conference_graph_size;
  191. vector<int> home_conference_vacation_graph_size;
  192.  
  193. vector<vector<Flight*> > flightsByDepartureCities;
  194. vector<vector<Flight*> > flightsByArrivalCities;
  195.  
  196. vector<vector<bool> > alliances;
  197.  
  198.  
  199.  
  200.  
  201.  
  202. void create_home_vacation_conference_graph(vector<Flight*> &flights, Parameters& parameters);
  203. void create_home_conference_vacation_graph(vector<Flight*> &flights, Parameters& parameters);
  204.  
  205. void find_home_conference_vacation_path(vector<Flight *> &flights, Parameters& parameters,
  206.                                                                                 cstr vacation, vector<dPair > &prev);
  207. void find_home_vacation_conference_path(vector<Flight*> &flights, Parameters& parameters,
  208.                                                                                 cstr vacation, vector<dPair > &prev);
  209.  
  210. time_t convert_to_timestamp(int day, int month, int year, int hour, int minute,
  211.                 int seconde);
  212. time_t convert_string_to_timestamp(cstr s);
  213.  
  214. void read_parameters(Parameters& parameters, int argc, char **argv);
  215.  
  216. void parse_flight(vector<Flight>& flights, cstr line, Parameters &parameters);
  217. void parse_flights(vector<Flight>& flights, File &flights_file, Parameters &parameters);
  218. void parse_alliance(cstr line);
  219. void parse_alliances(File &alliances_file);
  220.  
  221. void print_params(Parameters &parameters);
  222. void print_flight(Flight& flight, ofstream&);
  223. void print_alliances(vector<vector<int> > &alliances);
  224. void print_flights(vector<Flight>& flights, ofstream& output);
  225. void print_travel(Travel& travel, ofstream& output);
  226.  
  227. long get_time();
  228.  
  229. int add(cstr s, umap &m, int &counter, vector<cstr> &v);
  230. int add_company(cstr s);
  231. int add_city(cstr s);
  232. int add_id(cstr s);
  233. cstr get_from_pool(cstr c);
  234.  
  235. bool flightByTakeOffComparator(Flight* f1, Flight* f2);
  236. bool flightByArriveComparator(Flight* f1, Flight* f2);
  237. float getCostWithDiscount(Flight *fl, int type);
  238. bool can_fly(Flight* flight, ulong min_time, ulong max_time);
  239.  
  240. void fill_travel(vector<Flight*> &flights, int finish, int start,
  241.                 Travel &result, vector<dPair > &prev, int layersize);
  242. void dijkstra(Graph &graph, int start, int finish, vector<dPair > &prev);
  243. void wire_two_flights(Graph &g, Flight* f1, Flight* f2, int i1, int i2);
  244. void make_graph_layer(vector<Flight*> &flights, ulong min_time, ulong max_time,
  245.                 Graph& graph, int layer, int layersize, Parameters & params);
  246. void wire_two_layers(Graph &g, int from, int to, int city, int layersize, ulong l2, ulong r2);
  247.  
  248.  
  249.  
  250. /*
  251.  *      Dijkstra algorithm base on priority queue
  252.  *      Returns result in "prev" parameter which for any vertex will contain
  253.  *      previous vertex in path and distance to in (or -1 if there is no path
  254.  *      to this vertex)
  255.  */
  256. void dijkstra(Graph &graph, int start, int finish, vector<dPair > &prev) {
  257.         vector<double> d(graph.size(), FLOAT_INF);
  258.         prev.resize(graph.size());
  259.         d[start] = 0;
  260.  
  261.         priority_queue<dPair > q;
  262.         q.push(make_pair(0, start));
  263.         while (!q.empty()) {
  264.                 int v = q.top().second;
  265.                 if (v == finish) {
  266.                         break;
  267.                 }
  268.  
  269.                 double cur_d = -q.top().first;
  270.                 q.pop();
  271.                 if (cur_d > d[v] + EPS) {
  272.                         continue;
  273.                 }
  274.  
  275.                 for (size_t j = 0; j < graph[v].size(); ++j) {
  276.                         int to = graph[v][j].second;
  277.                         double len = graph[v][j].first;
  278.  
  279.                         if (d[v] + len < d[to]) {
  280.                                 d[to] = d[v] + len;
  281.                                 prev[to].first = d[v];
  282.                                 prev[to].second = v;
  283.                                 q.push(make_pair(-d[to], to));
  284.                         }
  285.                 }
  286.         }
  287.  
  288.         #pragma omp parallel for
  289.         for (size_t i = 0; i < graph.size(); ++i) {
  290.                 if (d[i] == FLOAT_INF) {
  291.                         prev[i].second = -1;
  292.                 }
  293.         }
  294. }
  295.  
  296. /*
  297.  *      Comparator for sorting flights by take off time
  298.  */
  299. bool flightByTakeOffComparator(Flight* f1, Flight* f2) {
  300.         return f1->take_off_time < f2->take_off_time;
  301. }
  302.  
  303. /*
  304.  *      Comparator for sorting flights by landing time
  305.  */
  306. bool flightByArriveComparator(Flight* f1, Flight* f2) {
  307.         return f1->land_time < f2->land_time;
  308. }
  309.  
  310. /*
  311.  *      Calculates flight cost with discount
  312.  */
  313. float getCostWithDiscount(Flight *fl, int type) {
  314.         if (type == 0) {
  315.                 return fl->cost;
  316.         } else if (type < 3) {
  317.                 return (fl->cost) * 0.7f;
  318.         } else {
  319.                 return (fl->cost) * 0.8f;
  320.         }
  321. }
  322.  
  323.  
  324. /*
  325.  *      Creates edges between two flights in graph
  326.  */
  327. void wire_two_flights(Graph &g, Flight* f1, Flight* f2, int i1, int i2) {
  328. #define P_B(t) push_back(make_pair(getCostWithDiscount(f2, t), i2 + t))
  329.         if(f1->company == f2->company) {
  330.                 g[i1 + FIRST_THIS].P_B(FROM_THIS);
  331.                 g[i1 + FROM_THIS].P_B(FROM_THIS);
  332.                 g[i1 + FROM_ALLIANCE].P_B(FROM_THIS);
  333.         } else if(alliances[f1->company][f2->company]) {
  334.                 g[i1 + FIRST_ALLIANCE].P_B(FROM_ALLIANCE);
  335.                 g[i1 + FIRST_ALLIANCE].P_B(FIRST_THIS);
  336.                 g[i1 + FROM_ALLIANCE].P_B(FROM_ALLIANCE);
  337.                 g[i1 + FROM_ALLIANCE].P_B(FIRST_THIS);
  338.                 g[i1 + FROM_THIS].P_B(FROM_ALLIANCE);
  339.                 g[i1 + FROM_THIS].P_B(FIRST_THIS);
  340.         } else {
  341.                 g[i1 + FROM_ANY].P_B(FROM_ANY);
  342.                 g[i1 + FROM_ANY].P_B(FIRST_THIS);
  343.                 g[i1 + FROM_ANY].P_B(FIRST_ALLIANCE);
  344.                 g[i1 + FROM_ALLIANCE].P_B(FROM_ANY);
  345.                 g[i1 + FROM_ALLIANCE].P_B(FIRST_THIS);
  346.                 g[i1 + FROM_ALLIANCE].P_B(FIRST_ALLIANCE);
  347.                 g[i1 + FROM_THIS].P_B(FROM_ANY);
  348.                 g[i1 + FROM_THIS].P_B(FIRST_THIS);
  349.                 g[i1 + FROM_THIS].P_B(FIRST_ALLIANCE);
  350.         }
  351. }
  352.  
  353. /*
  354.  *      Checks if it's possible to use given flight in given time interval
  355.  */
  356. bool can_fly(Flight* flight, ulong min_time, ulong max_time) {
  357.         return flight->take_off_time >= min_time && flight->land_time <= max_time;
  358. }
  359.  
  360. /*
  361.  *      Creates one graph layer. It will contain all flights which are in given time interval
  362.  */
  363. void make_graph_layer(vector<Flight*> &flights, ulong min_time, ulong max_time,
  364.                 Graph& graph, int layer, int layersize, Parameters & params) {
  365.  
  366.         int prod = layer * layersize;
  367.  
  368.         for (size_t i = 0; i < flights.size(); ++i) {
  369.                 Flight fake;
  370.                 Flight * current = flights[i];
  371.  
  372.                 if (!can_fly(current, min_time, max_time)) {
  373.                         continue;
  374.                 }
  375.  
  376.                 vector<Flight*> &fromVector = flightsByDepartureCities[current->to];
  377.                 ulong time_of_arrival = current->land_time;
  378.                 fake.take_off_time = time_of_arrival;
  379.                 vector<Flight*>::iterator lb = lower_bound(fromVector.begin(),
  380.                                 fromVector.end(), &fake, flightByTakeOffComparator);
  381.  
  382.                 while (lb != fromVector.end() &&
  383.                            (*lb)->take_off_time <= time_of_arrival + params.max_layover_time) {
  384.                         Flight *target = (*lb);
  385.                         if (can_fly(target, min_time, max_time)) {
  386.                                 wire_two_flights(graph, current, target,
  387.                                                                  prod + current->id * TYPES,
  388.                                                                  prod + target->id * TYPES);
  389.                         }
  390.                         ++lb;
  391.                 }
  392.         }
  393.  
  394.         int fromId = city_by_string[params.from];
  395.  
  396.         Flight fake;
  397.         fake.take_off_time = min_time;
  398.         vector<Flight*>::iterator firstFlight = lower_bound(
  399.                                 flightsByDepartureCities[fromId].begin(),
  400.                                 flightsByDepartureCities[fromId].end(), &fake,
  401.                                 flightByTakeOffComparator);
  402.         vector<fPair> &v = graph[(layer + 1) * layersize - 2];
  403.  
  404.         while (firstFlight != flightsByDepartureCities[fromId].end()
  405.                    && (*firstFlight)->take_off_time <= max_time) {
  406.                 if (can_fly(*firstFlight, min_time, max_time)) {
  407.                         for (int toType = 0; toType < 5; toType++) {
  408.                                 if (toType == 1 || toType == 3)
  409.                                         continue;
  410.                                 v.push_back(make_pair(getCostWithDiscount((*firstFlight), toType),
  411.                                                                           prod + TYPES * (*firstFlight)->id + toType));
  412.                         }
  413.                 }
  414.                 ++firstFlight;
  415.         }
  416.  
  417.         fake.land_time = min_time;
  418.         firstFlight = lower_bound(flightsByArrivalCities[fromId].begin(),
  419.                                                           flightsByArrivalCities[fromId].end(),
  420.                                                           &fake, flightByArriveComparator);
  421.         while (firstFlight != flightsByArrivalCities[fromId].end()
  422.                    && (*firstFlight)->land_time <= max_time) {
  423.                 if (can_fly(*firstFlight, min_time, max_time)) {
  424.                         for (int fromType = 0; fromType < 5; fromType++) {
  425.                                 if (fromType == 2 || fromType == 4)
  426.                                         continue;
  427.                                 graph[layersize * layer + TYPES * (*firstFlight)->id + fromType].push_back(
  428.                                                         make_pair(0, (layer + 1) * layersize - 1));
  429.                         }
  430.                 }
  431.                 ++firstFlight;
  432.         }
  433. }
  434.  
  435. /*
  436.  *      Connects two graph layers by given city using flights which are in given interval
  437.  */
  438. void wire_two_layers(Graph &g, int from, int to, int city, int layersize, ulong l2, ulong r2) {
  439.         vector<Flight*> &dep = flightsByDepartureCities[city];
  440.         vector<Flight*> &arr = flightsByArrivalCities[city];
  441.  
  442.         for (size_t i = 0; i < arr.size(); ++i) {
  443.                 ulong last_time = INT_INF;
  444.                 int index1 = layersize * from + arr[i]->id * TYPES;
  445.  
  446.                 for (size_t j = i + 1; j < arr.size(); ++j) {
  447.                         if (arr[i]->company == arr[j]->company) {
  448.                                 int index2 = layersize * from + arr[j]->id * TYPES;
  449.                                 for (int ty = 0; ty < TYPES; ++ty) {
  450.                                         g[index1 + ty].push_back(make_pair(0, index2 + ty));
  451.                                 }
  452.                                 last_time = arr[j]->land_time;
  453.                                 break;
  454.                         }
  455.                 }
  456.  
  457.                 Flight fake;
  458.                 fake.take_off_time = arr[i]->land_time;
  459.                 vector<Flight*>::iterator it = lower_bound(dep.begin(), dep.end(),
  460.                                 &fake, flightByTakeOffComparator);
  461.  
  462.                 while (it != dep.end()) {
  463.                         int index2 = layersize * to + (*it)->id * TYPES;
  464.                         Flight* flight1 = arr[i];
  465.                         Flight* flight2 = (*it);
  466.                         ulong t1 = flight2->take_off_time;
  467.                         ulong t2 = flight1->land_time;
  468.                         if (t1 > last_time)
  469.                                 break;
  470.                         if (t1 > t2 && can_fly(flight2, l2, r2)) {
  471.                                 wire_two_flights(g, flight1, flight2, index1, index2);
  472.                         }
  473.                         ++it;
  474.                 }
  475.         }
  476. }
  477.  
  478.  
  479. /*
  480.  *      Adds string to string pool if there is no such string in pool.
  481.  *      Else returns pointer to equal string in pool
  482.  */
  483. cstr get_from_pool(cstr c) {
  484.         unordered_set<cstr, cstr_hash, cstr_comparator>::iterator it = string_pool.find(c);
  485.         if (it == string_pool.end()) {
  486.                 string_pool.insert(c);
  487.                 return c;
  488.         } else {
  489.                 return *it;
  490.         }
  491. }
  492.  
  493.  
  494. /*
  495.  *      Adds company name to companies dictionary
  496.  */
  497. int add_company(cstr s) {
  498.         return add(get_from_pool(s), company_by_string, company_counter,
  499.                         company_by_index);
  500. }
  501.  
  502. /*
  503.  *      Adds city name to cities dictionary
  504.  */
  505. int add_city(cstr s) {
  506.         return add(get_from_pool(s), city_by_string, city_counter, city_by_index);
  507. }
  508.  
  509. /*
  510.  *      Adds id string to ids dictionary
  511.  */
  512. int add_id(cstr s) {
  513.         return add(get_from_pool(s), id_by_string, id_counter, id_by_index);
  514. }
  515.  
  516.  
  517. /*
  518.  *      Returns current system time in milliseconds
  519.  */
  520. long get_time() {
  521.         timeval time;
  522.         gettimeofday(&time, NULL);
  523.         return (time.tv_sec * 1000) + (time.tv_usec / 1000);
  524. }
  525.  
  526.  
  527. /*
  528.  *      Using dijkstra function output creates vector of flights to print.
  529.  */
  530. void fill_travel(vector<Flight*> &flights, int finish, int start,
  531.                 Travel &result, vector<dPair > &prev, int layersize) {
  532.         dPair v = prev[finish];
  533.         while (v.second != start) {
  534.                 if (!result.empty() && fabs(result.back().discount) < 1e-3) {
  535.                         result.pop_back();
  536.                 }
  537.                 int index = v.second % layersize / TYPES;
  538.                 Flight* f = flights[index];
  539.                 result.push_back(*f);
  540.                 result.back().discount = (v.first - prev[v.second].first) / result.back().cost;
  541.                 v = prev[v.second];
  542.         }
  543. }
  544.  
  545.  
  546.  
  547. /*
  548.  *      Restores initial graph structure
  549.  *      (removes information about vacation city which was added
  550.  *      while solving one of play hard tasks)
  551.  */
  552. void restore_graph(Graph &graph, vector<int> &graph_size) {
  553.         for (size_t i = 0; i < graph.size(); i++) {
  554.                 graph[i].resize(graph_size[i]);
  555.         }
  556. }
  557.  
  558. /*
  559.  *      Solves Work Hard task.
  560.  */
  561. Travel work_hard(vector<Flight*>& flights) {
  562.         int layersize = flights.size() * TYPES + 2;
  563.         int source_vertex = layersize - 2;
  564.         int target_vertex = layersize * 2 - 1;
  565.  
  566.         // it's possible to use home_conference_vacation_graph as
  567.         // Work Hard graph because we can not to connect the 2nd and the 3rd
  568.         // layers by vacation city
  569.         Graph &g = home_conference_vacation_graph;
  570.         vector<int> &g_size = home_conference_vacation_graph_size;
  571.  
  572.         restore_graph(g, g_size);
  573.  
  574.         vector<dPair > prev;
  575.         dijkstra(g, source_vertex, target_vertex, prev);
  576.  
  577.         // return result if exists
  578.         if (prev[target_vertex].second != -1) {
  579.                 Travel result;
  580.                 fill_travel(flights, target_vertex, source_vertex, result, prev, layersize);
  581.                 reverse(result.begin(), result.end());
  582.                 return result;
  583.         } else {
  584.                 return Travel();
  585.         }
  586. }
  587.  
  588.  
  589. /*
  590.  *      Constructs two graphs:
  591.  *      1. for home->vacation->conference path finding
  592.  *      2. for home->conference->vacation path finding (it can also be used for work hard task)
  593.  */
  594. void create_graphs(vector<Flight*> &flights, Parameters& parameters) {
  595.         #pragma omp parallel sections
  596.         {
  597.                 #pragma omp section
  598.                 create_home_vacation_conference_graph(flights, parameters);
  599.        
  600.                 #pragma omp section
  601.                 create_home_conference_vacation_graph(flights, parameters);
  602.         }
  603. }
  604.  
  605. /*
  606.  *      Creates graph for home->conference->vacation path finding (it can also be used for work hard task)
  607.  */
  608. void create_home_conference_vacation_graph(vector<Flight*> &flights, Parameters& parameters) {
  609.         int layersize = flights.size() * TYPES + 2;
  610.         Graph &g = home_conference_vacation_graph;
  611.         vector<int> &g_size = home_conference_vacation_graph_size;
  612.  
  613.         g.resize(layersize * 3);
  614.         g_size.resize(layersize * 3);
  615.  
  616.         ulong l0 = parameters.dep_time_min;
  617.         ulong r0 = parameters.dep_time_max;
  618.         ulong l1 = parameters.ar_time_min;
  619.         ulong r1 = parameters.ar_time_max;
  620.         ulong l2 = parameters.ar_time_max + parameters.vacation_time_min;
  621.         ulong r2 = parameters.ar_time_max + parameters.vacation_time_max;
  622.  
  623.         make_graph_layer(flights, l0, r0, g, 0, layersize, parameters);
  624.         make_graph_layer(flights, l1, r1, g, 1, layersize, parameters);
  625.         make_graph_layer(flights, l2, r2, g, 2, layersize, parameters);
  626.         wire_two_layers(g, 0, 1, city_by_string[parameters.to], layersize, l1, r1);
  627.        
  628.         for (size_t i = 0; i < g.size(); ++i) {
  629.                 g_size[i] = g[i].size();
  630.         }
  631. }
  632.  
  633.  
  634. /*
  635.  *      Creates graph for home->vacation->conference path finding
  636.  */
  637. void create_home_vacation_conference_graph(vector<Flight*> &flights, Parameters& parameters) {
  638.         int layersize = flights.size() * TYPES + 2;
  639.         Graph &g = home_vacation_conference_graph;
  640.         vector<int> &g_size = home_vacation_conference_graph_size;
  641.  
  642.         g.resize(layersize * 3);
  643.         g_size.resize(layersize * 3);
  644.  
  645.         ulong l0 = parameters.dep_time_min - parameters.vacation_time_max;
  646.         ulong r0 = parameters.dep_time_min - parameters.vacation_time_min;
  647.         ulong l1 = parameters.dep_time_min;
  648.         ulong r1 = parameters.dep_time_max;
  649.         ulong l2 = parameters.ar_time_min;
  650.         ulong r2 = parameters.ar_time_max;
  651.  
  652.         make_graph_layer(flights, l0, r0, g, 0, layersize, parameters);
  653.         make_graph_layer(flights, l1, r1, g, 1, layersize, parameters);
  654.         make_graph_layer(flights, l2, r2, g, 2, layersize, parameters);
  655.         wire_two_layers(g, 1, 2, city_by_string[parameters.to], layersize, l2, r2);
  656.  
  657.         for (size_t i = 0; i < g.size(); ++i) {
  658.                 g_size[i] = g[i].size();
  659.         }
  660. }
  661.  
  662.  
  663. /*
  664.  *      Solves "Play Hard" task for one vacation city.
  665.  */
  666. Travel play_hard_for_one(vector<Flight*> &flights, Parameters& parameters, cstr vacation) {
  667.         int layersize = flights.size() * TYPES + 2;
  668.         int source_vertex = layersize - 2;
  669.         int target_vertex = layersize * 3 - 1;
  670.  
  671.         vector<dPair > prev1;
  672.         find_home_vacation_conference_path(flights, parameters, vacation, prev1);
  673.  
  674.         vector<dPair > prev2;
  675.         find_home_conference_vacation_path(flights, parameters, vacation, prev2);
  676.  
  677.         // choosing the best from two ways (if there is)
  678.         if (prev1[target_vertex].second != -1 &&
  679.                         (prev2[target_vertex].second == -1 ||
  680.                          prev1[target_vertex].first < prev2[target_vertex].first)) {
  681.                 Travel result;
  682.                 fill_travel(flights, target_vertex, source_vertex, result, prev1, layersize);
  683.                 reverse(result.begin(), result.end());
  684.                 return result;
  685.         } else if (prev2[target_vertex].second != -1) {
  686.                 Travel result;
  687.                 fill_travel(flights, target_vertex, source_vertex, result, prev2, layersize);
  688.                 reverse(result.begin(), result.end());
  689.                 return result;
  690.         } else {
  691.                 return Travel();
  692.         }
  693. }
  694.  
  695.  
  696. void find_home_conference_vacation_path(vector<Flight*> &flights, Parameters& parameters,
  697.                                                                                 cstr vacation, vector<dPair > &prev) {
  698.         int layersize = flights.size() * TYPES + 2;
  699.         int source_vertex = layersize - 2;
  700.         int target_vertex = layersize * 3 - 1;
  701.  
  702.         Graph &g = home_conference_vacation_graph;
  703.         #pragma omp parallel for
  704.         for (size_t i = 0; i < g.size(); ++i) {
  705.                 g[i].resize(home_conference_vacation_graph_size[i]);
  706.         }
  707.         ulong l = parameters.ar_time_max + parameters.vacation_time_min;
  708.         ulong r = parameters.ar_time_max + parameters.vacation_time_max;
  709.         wire_two_layers(g, 1, 2, city_by_string[vacation], layersize, l, r);
  710.         dijkstra(g, source_vertex, target_vertex, prev);
  711. }
  712.  
  713.  
  714. void find_home_vacation_conference_path(vector<Flight*> &flights, Parameters& parameters,
  715.                                                                                 cstr vacation, vector<dPair > &prev) {
  716.         int layersize = flights.size() * TYPES + 2;
  717.         int source_vertex = layersize - 2;
  718.         int target_vertex = layersize * 3 - 1;
  719.  
  720.         Graph &g = home_vacation_conference_graph;
  721.         #pragma omp parallel for
  722.         for (size_t i = 0; i < g.size(); ++i) {
  723.                 g[i].resize(home_vacation_conference_graph_size[i]);
  724.         }
  725.         ulong l = parameters.dep_time_min;
  726.         ulong r = parameters.dep_time_max;
  727.         wire_two_layers(g, 0, 1, city_by_string[vacation], layersize, l, r);
  728.         dijkstra(g, source_vertex, target_vertex, prev);
  729. }
  730.  
  731.  
  732. /*
  733.  *      Solves "Play Hard" for all vacation cities and "Work Hard"
  734.  */
  735. vector<Travel> solve_task(vector<Flight*> &flights, Parameters& parameters) {
  736.         vector<Travel> result(parameters.airports_of_interest.size() + 1);
  737.         for (size_t i = 0; i <= parameters.airports_of_interest.size(); i++) {
  738.                 if (i == parameters.airports_of_interest.size()) {
  739.                         result[i] = work_hard(flights);
  740.                 } else {
  741.                         result[i] = play_hard_for_one(flights, parameters,
  742.                                         parameters.airports_of_interest[i]);
  743.                 }
  744.         }
  745.  
  746.         return result;
  747. }
  748.  
  749. vector<time_t> tc(100000);
  750. time_t get_time(int year, int month) {
  751.         size_t key = 13 * year + month;
  752.  
  753.         if(key >= tc.size()){
  754.                 tc.resize(key * 2);
  755.         }
  756.  
  757.         if (tc[key] == 0) {
  758.                 tm time;
  759.                 time.tm_year = year - 1900;
  760.                 time.tm_mon = month - 1;
  761.                 time.tm_mday = 0;
  762.                 time.tm_hour = time.tm_min = time.tm_sec = 0;
  763.                 time_t res = mktime(&time);
  764.                 tc[key] = res;
  765.         }
  766.  
  767.         return tc[key];
  768. }
  769.  
  770. time_t convert_to_timestamp(int day, int month, int year, int hour, int minute, int seconde) {
  771.         time_t res = get_time(year, month);
  772.         res += (day) * 60 * 60 * 24;
  773.         res += hour * 60 * 60;
  774.         res += minute * 60;
  775.         res += seconde;
  776.  
  777.         return res;
  778. }
  779.  
  780. void copy_substr(cstr dst, cstr src, int pos, int len) {
  781.         memcpy(dst, src + pos, len);
  782.         dst[len] = 0;
  783. }
  784.  
  785. time_t convert_string_to_timestamp(cstr s) {
  786.         if (strlen(s) != 14) {
  787.                 cerr << "The given string is not a valid timestamp" << endl;
  788.                 exit(0);
  789.         } else {
  790.                 char buf[5];
  791.                 int day, month, year, hour, minute, seconde;
  792.  
  793.                 copy_substr(buf, s, 2, 2);
  794.                 day = atoi(buf);
  795.                 copy_substr(buf, s, 0, 2);
  796.                 month = atoi(buf);
  797.                 copy_substr(buf, s, 4, 4);
  798.                 year = atoi(buf);
  799.                 copy_substr(buf, s, 8, 2);
  800.                 hour = atoi(buf);
  801.                 copy_substr(buf, s, 10, 2);
  802.                 minute = atoi(buf);
  803.                 copy_substr(buf, s, 12, 2);
  804.                 seconde = atoi(buf);
  805.                 return convert_to_timestamp(day, month, year, hour, minute, seconde);
  806.         }
  807. }
  808.  
  809. void print_params(Parameters &parameters) {
  810.         cout << "From : " << parameters.from << endl;
  811.         cout << "To : " << parameters.to << endl;
  812.         cout << "dep_time_min : " << parameters.dep_time_min << endl;
  813.         cout << "dep_time_max : " << parameters.dep_time_max << endl;
  814.         cout << "ar_time_min : " << parameters.ar_time_min << endl;
  815.         cout << "ar_time_max : " << parameters.ar_time_max << endl;
  816.         cout << "max_layover_time : " << parameters.max_layover_time << endl;
  817.         cout << "vacation_time_min : " << parameters.vacation_time_min << endl;
  818.         cout << "vacation_time_max : " << parameters.vacation_time_max << endl;
  819.         cout << "flights_file : " << parameters.flights_file << endl;
  820.         cout << "alliances_file : " << parameters.alliances_file << endl;
  821.         cout << "work_hard_file : " << parameters.work_hard_file << endl;
  822.         cout << "play_hard_file : " << parameters.play_hard_file << endl;
  823.         vector<cstr>::iterator it = parameters.airports_of_interest.begin();
  824.         for (; it != parameters.airports_of_interest.end(); it++)
  825.                 cout << "airports_of_interest : " << *it << endl;
  826.         cout << "flights : " << parameters.flights_file << endl;
  827.         cout << "alliances : " << parameters.alliances_file << endl;
  828.         cout << "nb_threads : " << parameters.nb_threads << endl;
  829. }
  830.  
  831. void print_flight(Flight& flight, ofstream& output) {
  832.         struct tm * take_off_t, *land_t;
  833.         take_off_t = gmtime(((const time_t*) &(flight.take_off_time)));
  834.         output << company_by_index[flight.company] << "-";
  835.         output << "" << id_by_index[flight.id] << "-";
  836.         output << city_by_index[flight.from] << " (" << (take_off_t->tm_mon + 1)
  837.                         << "/" << take_off_t->tm_mday << " " << take_off_t->tm_hour << "h"
  838.                         << take_off_t->tm_min << "min" << ")" << "/";
  839.         land_t = gmtime(((const time_t*) &(flight.land_time)));
  840.         output << city_by_index[flight.to] << " (" << (land_t->tm_mon + 1) << "/"
  841.                         << land_t->tm_mday << " " << land_t->tm_hour << "h"
  842.                         << land_t->tm_min << "min" << ")-";
  843.         output << flight.cost << "$" << "-" << flight.discount * 100 << "%" << endl;
  844.  
  845. }
  846.  
  847. void read_parameters(Parameters& parameters, int argc, char **argv) {
  848.         for (int i = 0; i < argc; i++) {
  849.                 string current_parameter = argv[i];
  850.                 if (current_parameter == "-from") {
  851.                         add_city(argv[++i]);
  852.                         parameters.from = get_from_pool(argv[i]);
  853.                 } else if (current_parameter == "-arrival_time_min") {
  854.                         parameters.ar_time_min = convert_string_to_timestamp(argv[++i]);
  855.                 } else if (current_parameter == "-arrival_time_max") {
  856.                         parameters.ar_time_max = convert_string_to_timestamp(argv[++i]);
  857.                 } else if (current_parameter == "-to") {
  858.                         add_city(argv[++i]);
  859.                         parameters.to = get_from_pool(argv[i]);
  860.                 } else if (current_parameter == "-departure_time_min") {
  861.                         parameters.dep_time_min = convert_string_to_timestamp(argv[++i]);
  862.                 } else if (current_parameter == "-departure_time_max") {
  863.                         parameters.dep_time_max = convert_string_to_timestamp(argv[++i]);
  864.                 } else if (current_parameter == "-max_layover") {
  865.                         parameters.max_layover_time = atol(argv[++i]);
  866.                 } else if (current_parameter == "-vacation_time_min") {
  867.                         parameters.vacation_time_min = atol(argv[++i]);
  868.                 } else if (current_parameter == "-vacation_time_max") {
  869.                         parameters.vacation_time_max = atol(argv[++i]);
  870.                 } else if (current_parameter == "-vacation_airports") {
  871.                         while (i + 1 < argc && argv[i + 1][0] != '-') {
  872.                                 add_city(argv[++i]);
  873.                                 parameters.airports_of_interest.push_back(
  874.                                                 get_from_pool(argv[i]));
  875.                         }
  876.                 } else if (current_parameter == "-flights") {
  877.                         parameters.flights_file = argv[++i];
  878.                 } else if (current_parameter == "-alliances") {
  879.                         parameters.alliances_file = argv[++i];
  880.                 } else if (current_parameter == "-work_hard_file") {
  881.                         parameters.work_hard_file = argv[++i];
  882.                 } else if (current_parameter == "-play_hard_file") {
  883.                         parameters.play_hard_file = argv[++i];
  884.                 } else if (current_parameter == "-nb_threads") {
  885.                         parameters.nb_threads = atoi(argv[++i]);
  886.                 }
  887.  
  888.         }
  889. }
  890.  
  891. vector<int> pos;
  892. void fill_pos(cstr line) {
  893.         pos.clear();
  894.         pos.push_back(0);
  895.         int len = strlen(line);
  896.         for (int i = 0; i < len; ++i) {
  897.                 if (line[i] == ';') {
  898.                         line[i] = 0;
  899.                         pos.push_back(i + 1);
  900.                 }
  901.         }
  902. }
  903.  
  904. bool interval_inside(ulong i1l, ulong i1r, ulong i2l, ulong i2r) {
  905.         return i1l >= i2l && i1r <= i2r;
  906. }
  907.  
  908. bool flight_needed(ulong land, ulong take, Parameters& parameters) {
  909.         return interval_inside(take, land, parameters.ar_time_min,
  910.                         parameters.ar_time_max) || interval_inside(take, land,
  911.                         parameters.dep_time_min, parameters.dep_time_max)
  912.                         || interval_inside(take, land, parameters.ar_time_max
  913.                                         + parameters.vacation_time_min, parameters.ar_time_max
  914.                                         + parameters.vacation_time_max) || interval_inside(take,
  915.                         land, parameters.dep_time_min - parameters.vacation_time_max,
  916.                         parameters.dep_time_min - parameters.vacation_time_min);
  917. }
  918.  
  919. void parse_flight(vector<Flight>& flights, cstr line, Parameters &parameters) {
  920.         fill_pos(line);
  921.         if (pos.size() == 7) {
  922.                 ulong land_time = convert_string_to_timestamp(get_from_pool(line
  923.                                 + pos[4]));
  924.                 ulong take_off_time = convert_string_to_timestamp(get_from_pool(line
  925.                                 + pos[2]));
  926.                 if (!flight_needed(land_time, take_off_time, parameters))
  927.                         return;
  928.  
  929.                 Flight flight;
  930.  
  931.                 flight.from = add_city(line + pos[1]);
  932.                 flight.take_off_time = take_off_time;
  933.                 flight.to = add_city(line + pos[3]);
  934.                 flight.land_time = land_time;
  935.                 flight.cost = atof(get_from_pool(line + pos[5]));
  936.                 flight.company = add_company(line + pos[6]);
  937.  
  938.                 flight.id = add(get_from_pool(line + pos[0]), id_by_string, id_counter,
  939.                                 id_by_index);
  940.                 flights.push_back(flight);
  941.         }
  942. }
  943.  
  944. int add(cstr s, umap &m, int &counter, vector<cstr> &v) {
  945.         umap::iterator i = m.find(s);
  946.         if (i == m.end()) {
  947.                 m.insert(make_pair(s, counter));
  948.                 v.push_back(s);
  949.                 return counter++;
  950.         } else {
  951.                 return i->second;
  952.         }
  953. }
  954.  
  955. void parse_flights(vector<Flight>& flights, File &flights_file,
  956.                 Parameters &parameters) {
  957.         flights_file.fopen();
  958.         istream input(flights_file.get_mapped_buf());
  959.         while (!input.eof()) {
  960.                 parse_flight(flights, flights_file.read_line(input), parameters);
  961.         }
  962.         flights_file.fclose();
  963. }
  964.  
  965. void parse_alliance(cstr line) {
  966.         fill_pos(line);
  967.         for (size_t i = 0; i < pos.size(); i++) {
  968.                 cstr line_i = get_from_pool(line + pos[i]);
  969.                 if (company_by_string.find(line_i) == company_by_string.end()) {
  970.                         continue;
  971.                 }
  972.                 for (size_t j = 0; j < pos.size(); ++j) {
  973.                         cstr line_j = get_from_pool(line + pos[j]);
  974.                         if (company_by_string.find(line_j) == company_by_string.end()) {
  975.                                 continue;
  976.                         }
  977.                         alliances[company_by_string[line_i]][company_by_string[line_j]]
  978.                                         = true;
  979.                 }
  980.         }
  981. }
  982.  
  983. void parse_alliances(File &alliances_file) {
  984.         alliances_file.fopen();
  985.         istream input(alliances_file.get_mapped_buf());
  986.         while (!input.eof()) {
  987.                 parse_alliance(alliances_file.read_line(input));
  988.         }
  989.         alliances_file.fclose();
  990. }
  991.  
  992. void print_alliances(vector<vector<int> > &alliances) {
  993.         for (size_t i = 0; i < alliances.size(); i++) {
  994.                 cout << "Alliance " << i << " : ";
  995.                 for (size_t j = 0; j < alliances[i].size(); j++) {
  996.                         cout << "**" << alliances[i][j] << "**; ";
  997.                 }
  998.                 cout << endl;
  999.         }
  1000. }
  1001.  
  1002. void print_flights(vector<Flight>& flights, ofstream& output) {
  1003.         for (size_t i = 0; i < flights.size(); i++)
  1004.                 print_flight(flights[i], output);
  1005. }
  1006.  
  1007. void print_travel(Travel& travel, ofstream& output) {
  1008.         float cost = 0;
  1009.         for (size_t i = 0; i < travel.size(); ++i) {
  1010.                 if (travel[i].discount > 0.9) {
  1011.                         travel[i].discount = 1;
  1012.                 } else if (travel[i].discount > 0.75) {
  1013.                         travel[i].discount = 0.8;
  1014.                 } else {
  1015.                         travel[i].discount = 0.7;
  1016.                 }
  1017.                 cost += (travel[i].cost * travel[i].discount);
  1018.         }
  1019.  
  1020.         output << "Price : " << cost << endl;
  1021.         print_flights(travel, output);
  1022.         output << endl;
  1023. }
  1024.  
  1025. void output_play_hard(vector<Travel>& travels, Parameters& parameters) {
  1026.         ofstream output;
  1027.         output.open(parameters.play_hard_file);
  1028.         vector<cstr> &cities = parameters.airports_of_interest;
  1029.         for (size_t i = 0; i < travels.size(); i++) {
  1030.                 output << "“Play Hard” Proposition " << (i + 1) << " : " << cities[i]
  1031.                                 << endl;
  1032.                 print_travel(travels[i], output);
  1033.                 output << endl;
  1034.         }
  1035.         output.close();
  1036. }
  1037.  
  1038. void output_work_hard(Travel &travel, Parameters& parameters) {
  1039.         ofstream output;
  1040.         output.open(parameters.work_hard_file);
  1041.         output << "“Work Hard”" << " Proposition :" << endl;
  1042.         print_travel(travel, output);
  1043.         output.close();
  1044. }
  1045.  
  1046. void fill_flights_by_cities(vector<Flight*> &flights) {
  1047.         flightsByDepartureCities.resize(city_counter);
  1048.         flightsByArrivalCities.resize(city_counter);
  1049.  
  1050.         for (size_t i = 0; i < flights.size(); ++i) {
  1051.                 Flight * fl = flights[i];
  1052.                 flightsByDepartureCities[fl->from].push_back(fl);
  1053.                 flightsByArrivalCities[fl->to].push_back(fl);
  1054.         }
  1055.  
  1056.         for (size_t i = 0; i < flightsByDepartureCities.size(); ++i) {
  1057.                 sort(flightsByDepartureCities[i].begin(),
  1058.                                 flightsByDepartureCities[i].end(), flightByTakeOffComparator);
  1059.                 sort(flightsByArrivalCities[i].begin(),
  1060.                                 flightsByArrivalCities[i].end(), flightByArriveComparator);
  1061.         }
  1062. }
  1063.  
  1064. int main(int argc, char **argv) {
  1065.         cstr tz = getenv("TZ");
  1066.         setenv("TZ", "", 1);
  1067.         tzset();
  1068.  
  1069.         Parameters parameters;
  1070.         read_parameters(parameters, argc, argv);
  1071.        
  1072.         omp_set_num_threads(parameters.nb_threads);
  1073.  
  1074.         File flights_file(parameters.flights_file);
  1075.         File alliances_file(parameters.alliances_file);
  1076.  
  1077.         vector<Flight> flights;
  1078.         flights.reserve(1000000);
  1079.         parse_flights(flights, flights_file, parameters);
  1080.  
  1081.         alliances.resize(company_counter);
  1082.         for (int i = 0; i < company_counter; ++i) {
  1083.                 alliances[i].resize(company_counter);
  1084.         }
  1085.  
  1086.         parse_alliances(alliances_file);
  1087.  
  1088.         vector<Flight*> f(flights.size());
  1089.         for (size_t i = 0; i < f.size(); ++i) {
  1090.                 f[i] = &flights[i];
  1091.         }
  1092.         fill_flights_by_cities(f);
  1093.  
  1094.         create_graphs(f, parameters);
  1095.         vector<Travel> travels = solve_task(f, parameters);
  1096.         Travel work_hard = travels.back();
  1097.         travels.pop_back();
  1098.         output_work_hard(work_hard, parameters);
  1099.         output_play_hard(travels, parameters);
  1100.  
  1101.         if (tz)
  1102.                 setenv("TZ", tz, 1);
  1103.         else
  1104.                 unsetenv("TZ");
  1105.         tzset();
  1106.  
  1107.         flights_file.dispose();
  1108.         alliances_file.dispose();
  1109. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement