Advertisement
Infernale

Shortest Summation Distance [NCTU Floor 9] [Greedy + D&C]

Jan 11th, 2020
497
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.76 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <sstream>
  4. #include <algorithm>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. struct Point{
  9.     int x, y;
  10.     Point(int x, int y){
  11.         this->x = x;
  12.         this->y = y;
  13.     }
  14. };
  15.  
  16. bool compareX(Point p1, Point p2){
  17.     return p1.x != p2.x ? (p1.x < p2.x) : (p1.y < p2.y);
  18. }
  19.  
  20. bool compareY(Point p1, Point p2){
  21.     return p1.y != p2.y ? (p1.y < p2.y) : (p1.x < p2.x);
  22. }
  23.  
  24. double getLength(Point a, Point b){
  25.     return hypot((a.x - b.x), (a.y - b.y));
  26. }
  27.  
  28. static double mini = INT_MAX;
  29.  
  30. void solveDivideAndConquer(vector <Point> vec, double sum){
  31.     double prevSum = sum;
  32.     if(sum >= mini){
  33.         return;
  34.     }
  35.     if(vec.size() == 2){
  36.         sum += getLength(vec[0], vec[1]);
  37.         mini = min(mini, sum);
  38.         return;
  39.     }
  40.     for(int i = 0; i < vec.size() - 1; i++){
  41.         for(int j = i + 1; j < vec.size(); j++){
  42.             sum = prevSum;
  43.             vector <Point> temp = vec;
  44.             sum += getLength(temp[i], temp[j]);
  45.             temp.erase(temp.begin() + j);
  46.             temp.erase(temp.begin() + i);
  47.             solveDivideAndConquer(temp, sum);
  48.         }
  49.     }
  50. }
  51.  
  52. double solveGreedy(vector <Point> points){
  53.     vector <bool> marked(points.size(), false);
  54.  
  55.     double sum = 0;
  56.     for(int i = 0; i < points.size(); i++){
  57.         if(!marked[i]){
  58.             marked[i] = true;
  59.             int nearest = i + 1, min_dist = -1;
  60.             for(int j = 0; j < points.size(); j++){
  61.                 if(marked[j] || i == j)
  62.                     continue;
  63.                 int x = points[i].x - points[j].x;
  64.                 int y = points[i].y - points[j].y;
  65.                 int m_dist = x * x + y * y;
  66.                 if(min_dist == -1 || min_dist > m_dist){
  67.                     min_dist = m_dist;
  68.                     nearest = j;
  69.                 }
  70.             }
  71.             marked[nearest] = true;
  72.             sum += sqrt(min_dist);
  73.         }
  74.     }
  75.     return sum;
  76. }
  77.  
  78. void estimateMini(vector <Point> points){
  79.     sort(points.begin(), points.end(), compareX);
  80.     double min1 = solveGreedy(points);
  81.     sort(points.begin(), points.end(), compareY);
  82.     double min2 = solveGreedy(points);
  83.     mini = min(min1, min2);
  84. }
  85.  
  86. int main(){
  87.     int n, x, y, index;
  88.     vector <Point> points;
  89.     string temp;
  90.     getline(cin, temp);
  91.     stringstream stream(temp);
  92.     while(stream >> n){
  93.         index = 0;
  94.         points.reserve(2 * n);
  95.         for(int i = 0; i < 2 * n; i++){
  96.             stream >> x >> y;
  97.             Point p(x, y);
  98.             points.push_back(p);
  99.         }
  100.         estimateMini(points);
  101.         if(n < 7)
  102.             solveDivideAndConquer(points, 0);
  103.         cout << fixed << setprecision(2) << mini << " ";
  104.         points.clear();
  105.     }
  106.     return 0;
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement