Guest User

TSP Solution #2

a guest
Jan 19th, 2012
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.70 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3. import java.math.*;
  4. import java.awt.geom.*;
  5.  
  6. public class Solution implements Runnable {
  7.  
  8.     public static void main(String[] args) throws Exception {
  9.         new Thread(null, new Solution(), "", 1 << 26).start();
  10.     }
  11.  
  12.     BufferedReader in;
  13.     PrintWriter out;
  14.     StringTokenizer st;
  15.  
  16.     final String fname = "";
  17.  
  18.     private String next() throws Exception {
  19.         if (st == null || !st.hasMoreElements())
  20.             st = new StringTokenizer(in.readLine());
  21.         return st.nextToken();
  22.     }
  23.  
  24.     private int nextInt() throws Exception {
  25.         return Integer.parseInt(next());
  26.     }
  27.  
  28.     private long nextLong() throws Exception {
  29.         return Long.parseLong(next());
  30.     }
  31.  
  32.     private double nextDouble() throws Exception {
  33.         return Double.parseDouble(next());
  34.     }
  35.  
  36.     public void run() {
  37.         try {
  38.             in = new BufferedReader(new InputStreamReader(System.in));
  39.             out = new PrintWriter(new OutputStreamWriter(System.out));
  40.             solve();
  41.         } catch (Exception ex) {
  42.             throw new RuntimeException(ex);
  43.         } finally {
  44.             out.close();
  45.         }
  46.     }
  47.    
  48.     static final double EPS = 1e-14;
  49.    
  50.     class Point implements Comparable<Point> {
  51.         double x,y;
  52.         int index;
  53.        
  54.         public Point(double x, double y, int index) {
  55.             this.x = x;
  56.             this.y = y;
  57.             this.index = index;
  58.         }
  59.        
  60.         @Override
  61.         public int compareTo(Point o) {
  62.             if (this.x < o.x) return -1;
  63.             if (this.x > o.x) return 1;
  64.             if (this.y < o.y) return -1;
  65.             if (this.y > o.y) return 1;
  66.             return 0;
  67.         }
  68.        
  69.     }
  70.    
  71.     double distance (Point a, Point b) {
  72.         return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  73.     }
  74.    
  75.     boolean cw (Point a, Point b, Point c) {
  76.         return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) < 0;
  77.     }
  78.  
  79.     boolean ccw (Point a, Point b, Point c) {
  80.         return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y) > 0;
  81.     }
  82.    
  83.    
  84.     ArrayList<Point> stupidAlgo (ArrayList<Point> a) {
  85.         int n = a.size();
  86.         double d [][] = new double [n][1<<n];
  87.         int preMask [][] = new int [n][1<<n];
  88.         int preVertex [][] = new int [n][1<<n];
  89.         for (int i = 0; i < n; i++) {
  90.             Arrays.fill(d [i], 1e3);
  91.             Arrays.fill(preVertex[i], -1);
  92.         }
  93.         for (int i = 0; i < n; i++)
  94.             d[i][(1<<i)] = 0.0;
  95.         for (int mask = 1; mask < (1<<n); mask++) {
  96.             for (int i = 0; i < n; i++) {
  97.                 if (((1<<i) & mask)>0) { // last
  98.                     for (int j = 0; j < n; j++)
  99.                         if (((1<<j) & mask)==0) { //next
  100.                             double dist = distance (a.get(i), a.get(j));
  101.                             int nextmask = (1<<j) | mask;
  102.                             if (d[j][nextmask] > d[i][mask] + dist) {
  103.                                 d[j][nextmask] = d[i][mask] + dist;
  104.                                 preMask[j][nextmask] = mask;
  105.                                 preVertex[j][nextmask] = i;
  106.                             }
  107.                         }
  108.                 }
  109.             }
  110.         }
  111.         int bestmask = (1<<n) - 1;
  112.         int besti = 17;
  113.         ArrayList<Point> ret = new ArrayList<Solution.Point> ();
  114.         ret.add(a.get(besti));
  115.         //restore
  116.         while (true) {
  117.             int prevmask = preMask[besti][bestmask];
  118.             int previ = preVertex[besti][bestmask];
  119.             if (previ == -1) break;
  120.             ret.add(a.get(previ));
  121.             besti = previ;
  122.             bestmask = prevmask;
  123.         }
  124.         return ret;
  125.     }
  126.    
  127.     ArrayList<Point> convexHull (ArrayList<Point> a) {
  128.         Collections.sort(a);
  129.         Point p1 = a.get(0);
  130.         Point p2 = a.get(a.size() - 1);
  131.         ArrayList<Point> up = new ArrayList<Solution.Point>();
  132.         ArrayList<Point> down = new ArrayList<Solution.Point>();
  133.         up.add(p1);
  134.         down.add(p1);
  135.         for (int i = 1; i < a.size(); i++) {
  136.             if (i == a.size() - 1 || cw (p1, a.get(i), p2)) {
  137.                 while (up.size() >= 2 && !cw (up.get(up.size() - 2), up.get(up.size() - 1), a.get(i)))
  138.                     up.remove(up.size() - 1);
  139.                 up.add(a.get(i));
  140.             }
  141.             if (i == a.size() - 1 || ccw (p1, a.get(i), p2)) {
  142.                 while (down.size() >= 2 && !ccw (down.get(down.size() - 2), down.get(down.size() - 1), a.get(i)))
  143.                     down.remove(down.size() - 1);
  144.                 down.add(a.get(i));
  145.                
  146.             }
  147.         }
  148.         ArrayList<Point> result = new ArrayList<Solution.Point>();
  149.         for (int i = 0; i < up.size(); i++)
  150.             result.add(up.get(i));
  151.         for (int i = down.size() - 2; i > 0; i--)
  152.             result.add(down.get(i));
  153.         return result;
  154.     }
  155.    
  156.     void reverse (ArrayList<Point> a) {
  157.         for (int i = 0; i < a.size()/2; i++) {
  158.             Point temp = a.get(i);
  159.             a.set(i, a.get(a.size() - i - 1));
  160.             a.set(a.size() - i - 1, temp);
  161.         }
  162.     }
  163.    
  164.     public void solve() throws Exception {
  165.         int n = nextInt();
  166.         ArrayList<Point> a = new ArrayList<Solution.Point>();
  167.         for (int i = 0; i < n; i++) {
  168.             a.add(new Point(nextDouble(), nextDouble(), i));
  169.         }
  170.         ArrayList<Point> convex = convexHull (a);
  171.        
  172.         for (Point p : convex) {
  173.             for (int i = 0; i < a.size(); i++) {
  174.                 if (a.get(i).index == p.index) {
  175.                     a.remove(i);
  176.                     break;
  177.                 }
  178.             }
  179.         }
  180.        
  181.         int m = convex.size();
  182.        
  183.         int count = 0;
  184.        
  185.         ArrayList<Point> ret = new ArrayList<Solution.Point>();
  186.        
  187.         for (int k = 0; k < n - m; k++) {
  188.             if (n - m - count == 20) {
  189.                 double bestDist = 1e3;
  190.                 int besti = -1;
  191.                 int bestj = -1;
  192.                 ArrayList<Point> stupid = stupidAlgo (a);
  193.                 reverse (stupid);
  194.                 for (int i = 0; i < convex.size(); i++) {
  195.                     int ii = (i + 1) % convex.size();
  196.                     for (int j = 0; j < stupid.size(); j++) {
  197.                         int jj = (j + 1) % stupid.size();
  198.                         double dist1 = distance(convex.get(i), stupid.get(j));
  199.                         double dist2 = distance(convex.get(ii), stupid.get(jj));
  200.                         double dist3 = distance(convex.get(i), convex.get(ii));
  201.                         double dist4 = distance(stupid.get(j), stupid.get(jj));
  202.                         double dist = dist1 + dist2 - dist3 - dist4;
  203.                         if (dist < bestDist) {
  204.                             bestDist = dist;
  205.                             besti = i;
  206.                             bestj = j;
  207.                         }
  208.                     }
  209.                 }
  210.                 for (int i = 0; i <= besti; i++)
  211.                     ret.add(convex.get(i));
  212.                 for (int i = bestj; i >= 0; i--)
  213.                     ret.add(stupid.get(i));
  214.                 for (int i = stupid.size() - 1; i >= bestj + 1; i--)
  215.                     ret.add(stupid.get(i));
  216.                 for (int i = besti + 1; i < convex.size(); i++)
  217.                     ret.add(convex.get(i));
  218.                 break;
  219.             }
  220.             int besti = -1;
  221.             int bestj = -1;
  222.             double bestDist = 1e9;
  223.             for (int i = 0; i < a.size(); i++) {
  224.                 double px = a.get(i).x;
  225.                 double py = a.get(i).y;
  226.                 for (int j = 0; j < convex.size(); j++) {
  227.                     int jj = (j + 1) % convex.size();
  228.                     double x1 = convex.get(j).x;
  229.                     double y1 = convex.get(j).y;
  230.                     double x2 = convex.get(jj).x;
  231.                     double y2 = convex.get(jj).y;
  232.                     double dist = Line2D.ptSegDist(x1, y1, x2, y2, px, py);
  233.                     if (dist < bestDist) {
  234.                         bestDist = dist;
  235.                         besti = i;
  236.                         bestj = jj;
  237.                     }
  238.                 }
  239.             }
  240.             convex.add(bestj, a.get(besti));
  241.             a.remove(besti);
  242.             count ++;
  243.         }
  244.        
  245.         double result = 0.0;
  246.         for (int i = 0; i < n; i++) {
  247.             int j = (i + 1) % n;
  248.             result += distance (ret.get(i), ret.get(j));
  249.         }
  250.        
  251.         out.printf("%.14f\n", result);
  252.         for (int i = 0; i < n; i++) {
  253.             out.print(ret.get(i).index + " ");
  254.         }
  255.        
  256.     }
  257.  
  258.  
  259. }
Advertisement
Add Comment
Please, Sign In to add comment