Tranvick

Salesman

Dec 4th, 2014
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.59 KB | None | 0 0
  1. #include <iostream>
  2. #include <memory.h>
  3. #include <cmath>
  4. #include <cstdio>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <ctime>
  8.  
  9. #define sqr(x) ((x) * (x))
  10.  
  11. const int N = 15;
  12. const double INF = 1e100;
  13.  
  14. double d[N][N];
  15. int n, k, path_len, path[N];
  16. double record = INF, dist[N];
  17. bool used[N], alive[N];
  18.  
  19. struct Point {
  20.     double x, y;
  21.     int hull_index;
  22.  
  23.     Point() : x(0.), y(0.), hull_index(0) {
  24.     }
  25.  
  26.     bool operator < (const Point &q) const {
  27.         if (hull_index == q.hull_index) {
  28.             return x < q.x || x == q.x && y < q.y;
  29.         } else {
  30.             return hull_index < q.hull_index;
  31.         }
  32.     }
  33.  
  34.     double dist(const Point &q) const {
  35.         return sqrt(sqr(x - q.x) + sqr(y - q.y));
  36.     }
  37.  
  38. } points[N], hull_points[N];
  39.  
  40. bool clock_wise(Point &a, Point &b, Point &c) {
  41.     return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) < 0;
  42. }
  43.  
  44. bool counter_clock_wise(Point &a, Point &b, Point &c) {
  45.     return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) > 0;
  46. }
  47.  
  48. std::istream& operator>>(std::istream &is, Point &p) {
  49.     is >> p.x >> p.y;
  50.     return is;
  51. }
  52.  
  53. std::vector<int> build_convex_hull() {
  54.     std::sort(points, points + n);
  55.     Point p1 = points[0], p2 = points[n - 1];
  56.     std::vector<int> up, down, result;
  57.     up.push_back(0);
  58.     down.push_back(0);
  59.     for (size_t i = 1; i < n; ++i) {
  60.         if (i == n - 1 || clock_wise(p1, points[i], p2)) {
  61.             while (up.size() >= 2 && !clock_wise(points[up[up.size()-2]], points[up[up.size()-1]], points[i]))
  62.                 up.pop_back();
  63.             up.push_back(i);
  64.         }
  65.         if (i == n - 1 || counter_clock_wise(p1, points[i], p2)) {
  66.             while (down.size() >= 2 && !counter_clock_wise(points[down[down.size()-2]], points[down[down.size()-1]], points[i]))
  67.                 down.pop_back();
  68.             down.push_back(i);
  69.         }
  70.     }
  71.     for (size_t i = 0; i < up.size(); ++i) {
  72.         result.push_back(up[i]);
  73.     }
  74.     for (size_t i = down.size()-2; i > 0; --i) {
  75.         result.push_back(down[i]);
  76.     }
  77.     return result;
  78. }
  79.  
  80. void input() {
  81.     std::cin >> n;
  82.     for (int i = 0; i < n; ++i) {
  83.         std::cin >> points[i];
  84.     }
  85. }
  86.  
  87. void precalculate_distances() {
  88.     for (int i = 0; i < n + k; ++i) {
  89.         for (int j = 0; j < n + k; ++j) {
  90.             d[i][j] = points[i].dist(points[j]);
  91.         }
  92.     }
  93. }
  94.  
  95. void preprocess() {
  96.     std::vector<int> hull_indicies = build_convex_hull();
  97.     for (size_t i = 0; i < hull_indicies.size(); ++i) {
  98.         points[hull_indicies[i]].hull_index = i + 1;
  99.     }
  100.     std::sort(points, points + n);
  101.     for (int i = 0; i < n; ++i) {
  102.         if (points[i].hull_index) {
  103.             hull_points[k++] = points[i];
  104.         }
  105.     }
  106.     n -= k;
  107.     precalculate_distances();
  108. }
  109.  
  110. inline double area(const Point &a, const Point &b, const Point &c) {
  111.     return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
  112. }
  113.  
  114. inline bool intersect(double a, double b, double c, double d) {
  115.     if (a > b) {
  116.         std::swap(a, b);
  117.     }
  118.     if (c > d) {
  119.         std::swap(c, d);
  120.     }
  121.     return std::max(a, c) <= std::min(b, d);
  122. }
  123.  
  124. bool segment_intersect(const Point &a, const Point &b, const Point &c, const Point &d) {
  125.     return intersect(a.x, b.x, c.x, d.x)
  126.         && intersect(a.y, b.y, c.y, d.y)
  127.         && area(a, b, c) * area(a, b, d) <= 1e-8
  128.         && area(c, d, a) * area(c, d, b) <= 1e-8;
  129. }
  130.  
  131. bool check_intersections(int v) {
  132.     for (int i = 1; i < path_len - 1; ++i) {
  133.         if (segment_intersect(points[path[i - 1]], points[path[i]], points[path[path_len - 1]], points[v])) {
  134.             return false;
  135.         }
  136.     }
  137.     return true;
  138. }
  139.  
  140. double mst_solution() {
  141.     memset(alive, 0, sizeof(alive));
  142.     for (int i = 0; i < n + k; ++i) {
  143.         dist[i] = INF;
  144.     }
  145.     int s = -1;
  146.     for (int i = 0; i < n + k && s < 0; ++i) {
  147.         if (!used[i]) {
  148.             s = i;
  149.             dist[s] = 0;
  150.         }
  151.     }
  152.     double result = 0;
  153.     while (true) {
  154.         int num = -1;
  155.         for (int i = 0; i < n + k; ++i) {
  156.             if (!used[i] && !alive[i] && (num == -1 || dist[i] < dist[num])) {
  157.                 num = i;
  158.             }
  159.         }
  160.         if (num == -1) {
  161.             break;
  162.         }
  163.         result += dist[num];
  164.         alive[num] = true;
  165.         for (int i = 0; i < n + k; ++i) {
  166.             dist[i] = std::min(dist[i], d[num][i]);
  167.         }
  168.     }
  169.     return result;
  170. }
  171.  
  172. void brut(int v, int used_from_hull, int used_not_from_hull, double dist) {
  173.     if (dist >= record || dist + mst_solution() >= record) {
  174.         return;
  175.     }
  176.     if (used_from_hull + used_not_from_hull == n + k) {
  177.         record = std::min(record, dist + d[v][n]);
  178.         return;
  179.     }
  180.     used[v] = true;
  181.     path[path_len++] = v;
  182.     if (used_from_hull < k) {
  183.         int to = n + used_from_hull;
  184.         if (check_intersections(to)) {
  185.             brut(to, used_from_hull + 1, used_not_from_hull, dist + d[v][to]);
  186.         }
  187.     }
  188.     if (used_not_from_hull < n) {
  189.         for (int i = 0; i < n; ++i) {
  190.             if (!used[i] && check_intersections(i)) {
  191.                 brut(i, used_from_hull, used_not_from_hull + 1, dist + d[v][i]);
  192.             }
  193.         }
  194.     }
  195.     used[v] = false;
  196.     --path_len;
  197. }
  198.  
  199. int main() {
  200.     freopen("input.txt", "r", stdin);
  201.     freopen("output.txt", "w", stdout);
  202.     clock_t begin = clock();
  203.     input();
  204.     preprocess();
  205.     record = 2 * mst_solution();
  206.     brut(n, 1, 0, 0);
  207.     std::cout << record << std::endl;
  208.     std::cerr << (clock() - begin) * 1. / CLOCKS_PER_SEC << std::endl;
  209.     return 0;
  210. }
Advertisement
Add Comment
Please, Sign In to add comment