c_cpp 计算站点之间的最低价格

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 计算站点之间的最低价格相关的知识,希望对你有一定的参考价值。

// $ g++ minPrice3.cpp --std=c++11
//
// Ticket Prices:
//
//            To
//      |  0  |  1  |  2  |  3  |  4  |
//    --+-----+-----+-----+-----+-----+
//    0 |  0  |  10 |  75 |  94 | 107 |
// F  --+-----+-----+-----+-----+-----+
// r  1 |  *  |  0  |  35 |  50 |  83 |
// o  --+-----+-----+-----+-----+-----+
// m  2 |  *  |  *  |  0  |  80 |  99 |
//    --+-----+-----+-----+-----+-----+
//    3 |  *  |  *  |  *  |  0  |  10 |
//    --+-----+-----+-----+-----+-----+
//    4 |  *  |  *  |  *  |  *  |  0  |
//
// Find the lowest price from station A to station B, where A <= B.
//
// Define LP(A, B) is the lowest price from A to B, then it could be
// calculated recursively by:
//
// LP(A, B) = Min(Price(A, B),
//                LP(A, A+1) + Price(A+1, B),
//                LP(A, A+2) + Price(A+2, B),
//                ...
//                LP(A, B-2) + Price(B-2, B))
//                LP(A, B-1) + Price(B-1, B))
//
// Tips:
// If we know how to solve the lowest price from station 0 to station N
// then the lowest price from station A to station B is same as
// the solution from the lowest price from station 0 to station B-A.

#include <cassert>
#include <iostream>
#include <vector>

#undef RECURSION
#undef MEMOIZATION
#undef DYNAMIC_PROGRAMMING
#undef RUN

#define RECURSION 1
#define MEMOIZATION 2
#define DYNAMIC_PROGRAMMING 3
// #define RUN RECURSION
// #define RUN MEMOIZATION
// #define RUN DYNAMIC_PROGRAMMING

// Store all the ticket prices between the stations by a 2D vector.
std::vector< std::vector<int> > Price; // Ticket prices.

#if RUN == RECURSION

// Get lowest price from station 0 to station n
unsigned int
LowestPrice(unsigned int n, std::vector< std::vector<int> >& price)
{
  assert(price.size() > n);

  if (n == 0 || n == 1) {
    return price[0][n];
  }

  // Assume the lowesr price is non-stop price.
  unsigned int min = price[0][n];
  // then compare it with stop
  for (unsigned int stop = 1 ; stop < n ; ++stop) {
    unsigned int cost = LowestPrice(stop, price) + price[stop][n];
    if (cost < min) {
      min = cost;
    }
  }

  return min;
}

#elif RUN == MEMOIZATION

// Get lowest price from station 0 to station n
unsigned int
LowestPrice(unsigned int n,
            std::vector< std::vector<int> >& price,
            std::vector<int>& memo)
{
  assert(price.size() > n && memo.size() >= n && price.size() >= memo.size());

  if (n == 0 || n == 1) {
    return price[0][n];
  }

  if (memo[n] < 0) {
    // Assume the lowesr price is non-stop price.
    unsigned int min = price[0][n];
    // then compare it with stop
    for (unsigned int stop = 1 ; stop < n ; ++stop) {
      unsigned int cost = LowestPrice(stop, price, memo) + price[stop][n];
      if (cost < min) {
        min = cost;
      }
    }
    memo[n] = min;
  }

  return memo[n];
}

// Get lowest price from station 0 to station n
unsigned int
LowestPrice(unsigned int n, std::vector< std::vector<int> >& price)
{
  assert(price.size() > n);

  std::vector<int> memo(price.size(), -1);
  return LowestPrice(n, price, memo);
}

#else // RUN == DYNAMIC_PROGRAMMING

// Get lowest price from station 0 to station n
unsigned int
LowestPrice(unsigned int n, std::vector< std::vector<int> >& price)
{
  assert(price.size() > n);

  std::vector<int> lp(n+1, -1);

  // LP(0, 0) = Price(0, 0), LP(0, 1) = Price(0, 1)
  lp[0] = price[0][0];
  if (lp.size() > 1) {
    lp[1] = price[0][1];
  }

  for (unsigned int i = 2 ; i <= n ; ++i) {
    // Assume the lowest price from 0 to i is the non-stop price first.
    lp[i] = price[0][i];
    for (unsigned int stop = 1 ; stop < n ; ++stop) {
      unsigned int cost = lp[stop] + price[stop][i];
      if (cost < lp[i]) {
        lp[i] = cost;
      }
    }
  }

  assert(lp[n] != -1);
  return lp[n];
}

#endif

// Get partial price table from station start to destination
std::vector< std::vector<int> >
GetPrice(unsigned int start, unsigned int destination)
{
  const unsigned int size = destination - start + 1;
  std::vector<std::vector<int>>
    offsetPrice(size, std::vector<int>(size, -1));

  for (unsigned int i = 0 ; i < offsetPrice.size() ; ++i) {
    for (unsigned int j = i ; j < offsetPrice.size() ; ++j) {
      offsetPrice[i][j] = Price[start + i][start + j];
    }
  }

  return offsetPrice;
}

// Get lowest price from station start to station destination
unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  std::vector< std::vector<int> > offsetPrice = GetPrice(start, destination);

  return LowestPrice(destination - start, offsetPrice);
}

int main()
{
  Price = {
    { 0, 10, 75, 94, 107 },
    { -1, 0, 35, 50, 83 },
    { -1, -1, 0, 80, 99 },
    { -1, -1, -1, 0, 10 },
    { -1, -1, -1, -1, 0 },
  };

  unsigned int start = 1;
  unsigned int dest = 4;
  unsigned int cost = LowestPrice(start, dest);

  std::cout << "Lowest price from " << start << " to " <<
               dest << " is " << cost << std::endl;

  return 0;
}
// $ g++ minPrice2.cpp --std=c++11
//
// Ticket Prices:
//
//            To
//      |  0  |  1  |  2  |  3  |  4  |
//    --+-----+-----+-----+-----+-----+
//    0 |  0  |  10 |  75 |  94 | 107 |
// F  --+-----+-----+-----+-----+-----+
// r  1 |  *  |  0  |  35 |  50 |  83 |
// o  --+-----+-----+-----+-----+-----+
// m  2 |  *  |  *  |  0  |  80 |  99 |
//    --+-----+-----+-----+-----+-----+
//    3 |  *  |  *  |  *  |  0  |  10 |
//    --+-----+-----+-----+-----+-----+
//    4 |  *  |  *  |  *  |  *  |  0  |
//
// Find the lowest price from station A to station B, where A <= B.
//
// Define LP(A, B) is the lowest price from A to B, then it could be
// calculated recursively by:
//
// LP(A, B) = Min(Price(A, B),
//                LP(A, A+1) + Price(A+1, B),
//                LP(A, A+2) + Price(A+2, B),
//                ...
//                LP(A, B-2) + Price(B-2, B))
//                LP(A, B-1) + Price(B-1, B))

#include <cassert>
#include <iostream>
#include <vector>

#undef RECURSION
#undef MEMOIZATION
#undef DYNAMIC_PROGRAMMING
#undef RUN

#define RECURSION 1
#define MEMOIZATION 2
#define DYNAMIC_PROGRAMMING 3
// #define RUN RECURSION
// #define RUN MEMOIZATION
// #define RUN DYNAMIC_PROGRAMMING

// Store all the ticket prices between the stations by a 2D vector.
std::vector< std::vector<int> > Price; // Ticket prices.

#if RUN == RECURSION

unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  if (start == destination || start + 1 == destination) {
    return Price[start][destination];
  }

  unsigned int min = Price[start][destination];
  for (unsigned int stop = start + 1 ; stop < destination ; ++stop) {
    unsigned int cost = LowestPrice(start, stop) + Price[stop][destination];
    if (cost < min) {
      min = cost;
    }
  }

  return min;
}

#elif RUN == MEMOIZATION

unsigned int
LowestPriceWithMemo(unsigned int start,
                    unsigned int destination,
                    std::vector<std::vector<int>>& memo)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  if (start == destination || start + 1 == destination) {
    return Price[start][destination];
  }

  if (memo[start][destination] < 0) {
    unsigned int min = Price[start][destination];
    for (unsigned int stop = start + 1 ; stop < destination ; ++stop) {
      unsigned int cost = LowestPrice(start, stop) + Price[stop][destination];
      if (cost < min) {
        min = cost;
      }
    }
    memo[start][destination] = min;
  }

  assert(memo[start][destination] != -1);
  return memo[start][destination];
}

unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  // Store the lowest prices between the stations by a 2D vector.
  std::vector<std::vector<int>>
    memo(Price.size(), std::vector<int>(Price[0].size(), -1));
  // Actually, we could only use a (dest-start+1)^2 table to save
  // all the lowest prices, but we need to use memo[a-offset][b-offset]
  // instead of memo[a][b] to record the lowest price from station a to b,
  // where offset = start here.

  return LowestPriceWithMemo(start, destination, memo);
}

#else // RUN == DYNAMIC_PROGRAMMING

// unsigned int
// LowestPrice(unsigned int start, unsigned int destination)
// {
//   assert(start <= destination);
//   assert(Price.size() > start && Price[0].size() > destination);

//   // Store the lowest prices between the stations from start to each station.
//   std::vector<int> lp(Price.size(), -1);
//   // Actually, we only need `destination-start+1` size vector here.

//   lp[start] = Price[start][start];
//   if (start + 1 < lp.size()) {
//     lp[start + 1] = Price[start][start + 1];
//   }

//   const unsigned int distance = destination - start;
//   for (unsigned int d = 2 ; d <= distance ; ++d) {
//     unsigned int last = start + d;
//     if (last > lp.size() - 1) {
//       break;
//     }

//     // Assume the lowest price is the non-stop price first.
//     lp[last] = Price[start][last];
//     for (unsigned int j = 1 ; j < d ; ++j) {
//       unsigned int stop = start + j;
//       unsigned int cost = lp[stop] + Price[stop][last];
//       if (cost < lp[last]) {
//         lp[last] = cost;
//       }
//     }
//   }

//   assert(lp[distance] != -1);
//   return lp[destination];
// }

unsigned int LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  // Store the lowest prices between the stations from start to each station.
  const unsigned int distance = destination - start;
  const unsigned int size = distance + 1;
  // lp[x] = lowest prices from start to start+x.
  std::vector<int> lp(size, -1);

  // LP(start, start) = Price(start, start),
  // LP(start, start+1) = Price(start, start+1)
  lp[0] = Price[start][start];
  if (1 < lp.size()) {
    lp[1] = Price[start][start + 1];
  }

  for (unsigned int d = 2 ; d <= distance ; ++d) {
    // Assume the lowest price is the non-stop price first.
    unsigned int last = start + d;
    lp[d] = Price[start][last];
    for (unsigned int j = 1 ; j < d ; ++j) {
      unsigned int stop = start+j;
      unsigned int cost = lp[j] + Price[stop][last];
      if (cost < lp[d]) {
        lp[d] = cost;
      }
    }
  }

  assert(lp[distance] != -1);
  return lp[distance];
}

#endif

int main()
{
  Price = {
    { 0, 10, 75, 94, 107 },
    { -1, 0, 35, 50, 83 },
    { -1, -1, 0, 80, 99 },
    { -1, -1, -1, 0, 10 },
    { -1, -1, -1, -1, 0 },
  };

  unsigned int start = 1;
  unsigned int dest = 4;
  unsigned int cost = LowestPrice(start, dest);

  std::cout << "Lowest price from " << start << " to " <<
               dest << " is " << cost << std::endl;

  return 0;
}
// $ g++ minPrice1.cpp --std=c++11
//
// Ticket Prices:
//
//            To
//      |  0  |  1  |  2  |  3  |  4  |
//    --+-----+-----+-----+-----+-----+
//    0 |  0  |  10 |  75 |  94 | 107 |
// F  --+-----+-----+-----+-----+-----+
// r  1 |  *  |  0  |  35 |  50 |  83 |
// o  --+-----+-----+-----+-----+-----+
// m  2 |  *  |  *  |  0  |  80 |  99 |
//    --+-----+-----+-----+-----+-----+
//    3 |  *  |  *  |  *  |  0  |  10 |
//    --+-----+-----+-----+-----+-----+
//    4 |  *  |  *  |  *  |  *  |  0  |
//
// Find the lowest price from station A to station B, where A <= B.
//
// Define LP(A, B) is the lowest price from A to B, then it could be
// calculated recursively by:
//
// LP(A, B) = Min(Price(A, B),
//                LP(A, A+1) + LP(A+1, B),
//                LP(A, A+2) + LP(A+2, B),
//                ...
//                LP(A, B-2) + LP(B-2, B))
//                LP(A, B-1) + LP(B-1, B))

#include <cassert>
#include <iostream>
#include <vector>

#undef RECURSION
#undef MEMOIZATION
#undef DYNAMIC_PROGRAMMING
#undef RUN

#define RECURSION 1
#define MEMOIZATION 2
#define DYNAMIC_PROGRAMMING 3
// #define RUN RECURSION
// #define RUN MEMOIZATION
#define RUN DYNAMIC_PROGRAMMING

// Store all the ticket prices between the stations by a 2D vector.
std::vector< std::vector<int> > Price; // Ticket prices.

#if RUN == RECURSION

unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  if (start == destination || start + 1 == destination) {
    return Price[start][destination];
  }

  unsigned int min = Price[start][destination];
  for (unsigned int stop = start + 1 ; stop < destination ; ++stop) {
    unsigned int cost = LowestPrice(start, stop) +
                        LowestPrice(stop, destination);
    if (cost < min) {
      min = cost;
    }
  }

  return min;
}

#elif RUN == MEMOIZATION

unsigned int
LowestPriceWithMemo(unsigned int start,
                    unsigned int destination,
                    std::vector<std::vector<int>>& memo)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  if (start == destination || start + 1 == destination) {
    // memo[start][destination] = Price[start][destination];
    return Price[start][destination];
  }

  if (memo[start][destination] < 0) {
    unsigned int min = Price[start][destination];
    for (unsigned int stop = start + 1 ; stop < destination ; ++stop) {
      unsigned int cost = LowestPriceWithMemo(start, stop, memo) +
                          LowestPriceWithMemo(stop, destination, memo);
      if (cost < min) {
        min = cost;
      }
    }
    memo[start][destination] = min;
  }

  assert(memo[start][destination] != -1);
  return memo[start][destination];
}

unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  // Store the lowest prices between the stations by a 2D vector.
  std::vector<std::vector<int>>
    memo(Price.size(), std::vector<int>(Price[0].size(), -1));
  // Actually, we could only use a (dest-start+1)^2 table to save
  // all the lowest prices, but we need to use memo[a-offset][b-offset]
  // instead of memo[a][b] to record the lowest price from station a to b,
  // where offset = start here.

  return LowestPriceWithMemo(start, destination, memo);
}

#else // RUN == DYNAMIC_PROGRAMMING

// unsigned int
// LowestPrice(unsigned int start, unsigned int destination)
// {
//   assert(start <= destination);
//   assert(Price.size() > start && Price[0].size() > destination);

//   // Store the lowest prices between the stations by a 2D vector.
//   // lp[i][j] = minimal distance from i to j.
//   std::vector<std::vector<int>>
//     lp(Price.size(), std::vector<int>(Price[0].size(), -1));
//   // Actually, we could only use a (dest-start+1)^2 table to save
//   // all the lowest prices.

//   // LP(a, b) = Price(a, b) if b = a or b = a + 1.
//   for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//     lp[i][i] = Price[i][i];
//     if (i + 1 < lp[i].size()) {
//       lp[i][i + 1] = Price[i][i + 1];
//     }
//   }

//   const unsigned int distance = destination - start;
//   for (unsigned int d = 2 ; d <= distance ; ++d) {
//     for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//       unsigned int last = i + d;
//       if (last > lp.size() - 1) {
//         break;
//       }
//       // Assume the minimal price from state i to last is the non-stop price.
//       lp[i][last] = Price[i][last];
//       // Iteratively check the minimal price.
//       for (unsigned int j = 1 ; j < d ; ++j) {
//         unsigned int stop = i + j;
//         unsigned int cost = lp[i][stop] + lp[stop][last];
//         if (lp[i][last] > cost) {
//           lp[i][last] = cost;
//         }
//       }
//     }
//   }

//   assert(lp[start][destination] != -1);
//   return lp[start][destination];
// }

// unsigned int
// LowestPrice(unsigned int start, unsigned int destination)
// {
//   assert(start <= destination);
//   assert(Price.size() > start && Price[0].size() > destination);

//   // Store the lowest prices between the stations by a 2D vector.
//   // lp[i][j] = minimal distance from i to j.
//   std::vector<std::vector<int>>
//     lp(Price.size(), std::vector<int>(Price[0].size(), -1));
//   // Actually, we could only use a (dest-start+1)^2 table to save
//   // all the lowest prices.

//   // Assume the minimal price from state start+i
//   // to start+farmost is the non-stop price.
//   for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//     for (unsigned int j = i ; j < lp[i].size() ; ++j) {
//       lp[i][j] = Price[i][j];
//     }
//   }

//   // LP(a, b) = Price(a, b) if b = a or b = a + 1,
//   // so we don't need to check the
//   // prices between stations whose distance is 0 or 1.
//   const unsigned int distance = destination - start;
//   for (unsigned int d = 2 ; d <= distance ; ++d) {
//     for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//       unsigned int last = i + d;
//       if (last > lp.size() - 1) {
//         break;
//       }
//       // Iteratively check the minimal price.
//       for (unsigned int j = 1 ; j < d ; ++j) {
//         unsigned int stop = i + j;
//         unsigned int cost = lp[i][stop] + lp[stop][last];
//         if (lp[i][last] > cost) {
//           lp[i][last] = cost;
//         }
//       }
//     }
//   }

//   assert(lp[start][destination] != -1);
//   return lp[start][destination];
// }

// unsigned int
// LowestPrice(unsigned int start, unsigned int destination)
// {
//   assert(start <= destination);
//   assert(Price.size() > start && Price[0].size() > destination);

//   // Store the lowest prices between the stations by a 2D vector.
//   // lp[i][j] = minimal distance from start+i to start+j
//   const unsigned int distance = destination - start;
//   const unsigned int size = distance + 1;
//   std::vector<std::vector<int>>
//     lp(size, std::vector<int>(size, -1));

//   // LP(a, b) = Price(a, b) if b = a or b = a + 1.
//   for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//     lp[i][i] = Price[start+i][start+i];
//     if (i + 1 < lp[i].size()) {
//       lp[i][i + 1] = Price[start + i][start + i + 1];
//     }
//   }

//   for (unsigned int d = 2 ; d <= distance ; ++d) {
//     for (unsigned int i = 0 ; i < lp.size() ; ++i) {
//       unsigned int farmost = i + d;
//       if (farmost > lp.size() - 1) {
//         break;
//       }
//       // Assume the minimal price from state start+i
//       // to start+farmost is the non-stop price.
//       lp[i][farmost] = Price[start + i][start + farmost];
//       // Iteratively check the minimal price.
//       for (unsigned int j = 1 ; j < d ; ++j) {
//         unsigned int stop = i + j;
//         unsigned int cost = lp[i][stop] + lp[stop][farmost];
//         if (lp[i][farmost] > cost) {
//           lp[i][farmost] = cost;
//         }
//       }
//     }
//   }

//   assert(lp[0][distance] != -1);
//   return lp[0][distance];
// }

unsigned int
LowestPrice(unsigned int start, unsigned int destination)
{
  assert(start <= destination);
  assert(Price.size() > start && Price[0].size() > destination);

  // Store the lowest prices between the stations by a 2D vector.
  // lp[i][j] = minimal distance from start+i to start+j
  const unsigned int distance = destination - start;
  const unsigned int size = distance + 1;
  std::vector<std::vector<int>>
    lp(size, std::vector<int>(size, -1));

  // Assume the minimal price from state start+i
  // to start+farmost is the non-stop price.
  for (unsigned int i = 0 ; i < lp.size() ; ++i) {
    for (unsigned int j = i ; j < lp[i].size() ; ++j) {
      lp[i][j] = Price[start + i][start + j];
    }
  }

  // LP(a, b) = Price(a, b) if b = a or b = a + 1,
  // so we don't need to check the prices between
  // stations whose distance is 0 or 1.
  for (unsigned int d = 2 ; d <= distance ; ++d) {
    for (unsigned int i = 0 ; i < lp.size() ; ++i) {
      unsigned int farmost = i + d;
      if (farmost > lp.size() - 1) {
        break;
      }
      // Iteratively check the minimal price.
      for (unsigned int j = 1 ; j < d ; ++j) {
        unsigned int stop = i + j;
        unsigned int cost = lp[i][stop] + lp[stop][farmost];
        if (lp[i][farmost] > cost) {
          lp[i][farmost] = cost;
        }
      }
    }
  }

  assert(lp[0][distance] != -1);
  return lp[0][distance];
}

#endif

int main()
{
  Price = {
    { 0, 10, 75, 94, 107 },
    { -1, 0, 35, 50, 83 },
    { -1, -1, 0, 80, 99 },
    { -1, -1, -1, 0, 10 },
    { -1, -1, -1, -1, 0 },
  };

  unsigned int start = 1;
  unsigned int dest = 4;
  unsigned int cost = LowestPrice(start, dest);

  std::cout << "Lowest price from " << start << " to " <<
               dest << " is " << cost << std::endl;

  return 0;
}

以上是关于c_cpp 计算站点之间的最低价格的主要内容,如果未能解决你的问题,请参考以下文章

课堂练习--计算购买一批书最低价格

神经网络算法预测3月竞拍价格

课堂练习---最低价格买书

求最低价格

求购买一批打折书的最低价格

Price Transform 价格转换(TA-lib)