How to compute optimal paths for traveling salesman bitonic tour?

后端 未结 2 757
别那么骄傲
别那么骄傲 2020-12-28 18:54

UPDATED

After more reading, the solution can be given with the following recurrence relation:

(a) When i = 1 and j = 2, l(i; j) = di         


        
相关标签:
2条回答
  • 2020-12-28 19:15

    Clarification on your algorithm.

    The l(i,j) recursive function should compute the minimum distance of a bitonic tour i -> 1 -> j visiting all nodes that are smaller than i. So, the solution to the initial problem will be l(n,n)!

    Important notes:

    1. we can assume that the nodes are ordered by their x coordinate and labeled accordingly (p1.x < p2.x < p3.x ... < pn.x). It they weren't ordered, we could sort them in O(nlogn) time.

    2. l(i,j) = l(j,i). The reason is that in the lhs, we have a i ->...-> 1 -> ... -> j tour which is optimal. However traversing this route backward will give us the same distance, and won't broke bitonic property.

    Now the easy cases (note the changes!):

    (a) When i = 1 and j = 2, l(i; j) = dist(pi; pj ) = dist(1,2)
    

    Here we have the following tour : 1->1->...->2. Trivially this is equivalent to the length of the path 1->...->2. Since points are ordered by their .x coordinate, there is no point between 1 and 2, so the straight line connecting them will be the optimal one. ( Choosing any number of other points to visit before 2 would result in a longer path! )

    (b) When i < j - 1; l(i; j) = l(i; j - 1) + dist(pj-1; pj)
    

    In this case, j-1 must be on the part of the path 1 -> ... -> j, because the part i -> ... -> 1 can not contain nodes with an index bigger than i. Because all nodes in the path 1 -> ... -> j are in increasing order of index, there can be none between j-1 and j. So, this is equivalent to the tour: i -> ... -> 1 -> .... -> j-1 -> j, which is equivalent to l(i,j-1) + dist(pj-1,pj)!

    Anf finally the interesting part comes:

    (c) When i = j - 1 or i = j, min 1<=k<i (l(k; i) + dist(pk; pj ))
    

    Here we know that we have to get from i to 1, but there is no clue on the backward sweep! The key idea here is that we must think of the node just before j on our backward route. It may be any of the nodes from 1 to j-1! Let us assume that this node is k. Now we have a tour: i -> ... -> 1 -> .... -> k -> j, right? The cost of this tour is l(i,k) + dist(pk,pj).

    Hope you got it.

    Implementation.

    You will need a 2-dimensional array say BT[1..n][1..n]. Let i be the row index, j be the column index. How should we fill in this table?

    In the first row we know BT[1][1] = 0, BT[1][2] = d(1,2), so we have only i,j indexes left that fall into the (b) category.

    In the remainin rows, we fill the elements from the diagonal till the end.

    Here is a sample C++ code (not tested):

    void ComputeBitonicTSPCost( const std::vector< std::vector<int> >& dist, int* opt ) {
      int n = dist.size();
      std::vector< std::vector< int > > BT;
      BT.resize(n);
      for ( int i = 0; i < n; ++i )
        BT.at(i).resize(n);
    
      BT.at(0).at(0) = 0;  // p1 to p1 bitonic distance is 0
      BT.at(0).at(1) = dist.at(0).at(1);  // p1 to p2 bitonic distance is d(2,1)
    
      // fill the first row
      for ( int j = 2; j < n; ++j )
        BT.at(0).at(j) = BT.at(0).at(j-1) + dist.at(j-1).at(j);
    
      // fill the remaining rows
      int temp, min;  
      for ( int i = 1; i < n; ++i ) {
        for ( int j = i; j < n; ++j ) {
          BT.at(i).at(j) = -1;
          min = std::numeric_limits<int>::max();
          if ( i == j || i == j -1 ) {
            for( int k = 0; k < i; ++k ) {
              temp = BT.at(k).at(i) + dist.at(k).at(j);
              min = ( temp < min ) ? temp : min;
            }        
            BT.at(i).at(j) = min;        
          } else {
            BT.at(i).at(j) = BT.at(i).at(j-1) + dist.at(j-1).at(j);
          }
        }
      }
    
      *opt = BT.at(n-1).at(n-1);
    }
    

    0 讨论(0)
  • 2020-12-28 19:19

    Okay, the key notions in a dynamic programming solution are:

    • you pre-compute smaller problems
    • you have a rule to let you combine smaller problems to find solutions for bigger problems
    • you have a known property of the problems that let's you prove the solution is really optimal under some measure of optimality. (In this case, shortest.)

    The essential property of a bitonic tour is that a vertical line in the coordinate system crosses a side of the closed polygon at most twice. So, what is a bitonic tour of exactly two points? Clearly, any two points form a (degenerate) bitonic tour. Three points have two bitonic tours ("clockwise" and "counterclockwise").

    Now, how can you pre-compute the various smaller bitonic tours and combine them until you have all points included and still have a bitonic tour?


    Okay, you're on the righ track with your update. But now, in a dynamic programming solution, what you do with work it bottom-up: pre-compute and memoize (not "memorize") the optimal subproblems.

    0 讨论(0)
提交回复
热议问题