Horse moves and returns to its starting position in a chessboard

This is a typical problem of searching. From the problem itself, we know that recursive programming is suitable to solve it. Below is the c++ code to calculate the total number of possible routes for a horse to move and return to a given starting position within the chessboard.

  1. #include <iostream>
  2. using namespace std;
  3. const int NUMBER_OF_DIRECTIONS = 8; // Number of directions the horse can go.
  4. const int NUMBER_OF_DIMENSIONS = 2; // Number of dimensions of space the horse can move.
  5. // The possible 8 directions the horse can go.
  6. int direction[NUMBER_OF_DIMENSIONS][NUMBER_OF_DIRECTIONS] = {
  7.     {-1, -1, -2, -2,  2,  2,  1,  1},
  8.     {-2,  2,  1, -1,  1, -1,  2, -2}};
  9. // Return true if [start_m][start_n] is in the board of [m][n].
  10. inline bool in_board(int m, int n, int start_m, int start_n) {
  11.     return (start_m >= 0 && start_m < m && start_n >= 0 && start_n < n);
  12. }
  13. // The recursive function to traverse all the routes in the board that the horse can go to return to its starting position.
  14. void traverse_routes(int* chessboard, int m, int n, int start_m, int start_n, int curr_m, int curr_n, int& number_of_routes) {
  15.     int next_m, next_n;
  16.     *(chessboard + curr_m * n + curr_n) = 1; // The horse has been in this current position.
  17.     for(int i = 0; i < NUMBER_OF_DIRECTIONS; ++i) { // Try every direction the horse can move.
  18.         next_m = curr_m + direction[0][i];
  19.         next_n = curr_n + direction[1][i];
  20.         if(in_board(m, n, next_m, next_n) && *(chessboard + next_m * n + next_n) == 0) { // If next position is in the board.
  21.             traverse_routes(chessboard, m, n, start_m, start_n, next_m, next_n, number_of_routes); // Go to that position can recursively traverse from that position.
  22.         }
  23.         else if(next_m == start_m && next_n == start_n) { // If next position is the starting position.
  24.             ++number_of_routes; // One route is found.
  25.         }
  26.     }
  27.     *(chessboard + curr_m * n + curr_n) = 0; // The horse has not been in this current position.
  28. }
  29. // A wrapper method for the horse route traversal problem.
  30. int horse_route_traversal(int m, int n, int start_m, int start_n) {
  31.     int* chessboard, number_of_routes;
  32.     // Initialization of the auxiliary memory.
  33.     chessboard = new int[m*n];
  34.     memset(chessboard, 0, m*n*sizeof(int));
  35.     number_of_routes = 0;
  36.     // Call the recursive function.
  37.     traverse_routes(chessboard, m, n, start_m, start_n, start_m, start_n, number_of_routes);
  38.     // Free dynamic-allocated memory.
  39.     delete[] chessboard;
  40.     return number_of_routes;
  41. }
  42. int main() {
  43.     int m, n, start_m, start_n, number_of_routes;
  44.     
  45.     // Input the parameters.
  46.     cout << "Input the size of chessboard (m n):" << endl;
  47.     cin >> m >> n;
  48.     while(!(m > 0 && n > 0)) {
  49.         cout << "m and n should be positive both." << endl;
  50.         cin >> m >> n;
  51.     }
  52.     cout << "Input the starting position of the horse (start_m start_n):" << endl;
  53.     cin >> start_m >> start_n;
  54.     while(!in_board(m, n, start_m, start_n)) {
  55.         cout << "start_m and start_n should be in [0, m) and [0, n) repectively." << endl;
  56.         cin >> start_m >> start_n;
  57.     }
  58.     
  59.     // Get the total number of the horse routes.
  60.     number_of_routes = horse_route_traversal(m, n, start_m, start_n);
  61.     
  62.     // Output information.
  63.     cout << "Board size:       " << m << "*" << n << endl;
  64.     cout << "Start point:      (" << start_m << ", " << start_n << ")" << endl;
  65.     cout << "Number of routes: " << number_of_routes << endl;
  66.     
  67.     return 0;
  68. }

Notice that the indices for a position follows the convention which starts an array by ZERO. So the position (0,0) is legal and represents the leftmost and lowest position of a chessboard. Here is a test case: the board's size is 4*5, i.e., the board has 4 lines, each of which has 5 columns. The starting position is (0,0). The total number of routes is 1508. Another test case: the board's size is 4*5, and the starting position is (1,1). Then the number of routes is 4596.

 

 

 

OK. What if we want to see how the horse moves and returns step by step? Then we need to store every step that the horse moves and that is contained in a legal route. The following is the modified version of program which is able to record the details of all the possible routes and save them into a file named "Horse.txt".

  1. #include <iostream>
  2. #include <vector>
  3. #include <fstream>
  4. using namespace std;
  5. const int NUMBER_OF_DIRECTIONS = 8; // Number of directions the horse can go.
  6. const int NUMBER_OF_DIMENSIONS = 2; // Number of dimensions of space the horse can move.
  7. // The possible 8 directions the horse can go.
  8. int direction[NUMBER_OF_DIMENSIONS][NUMBER_OF_DIRECTIONS] = {
  9.     {-1, -1, -2, -2,  2,  2,  1,  1},
  10.     {-2,  2,  1, -1,  1, -1,  2, -2}};
  11. // Return true if [start_m][start_n] is in the board of [m][n].
  12. inline bool in_board(int m, int n, int start_m, int start_n) {
  13.     return (start_m >= 0 && start_m < m && start_n >= 0 && start_n < n);
  14. }
  15. // The recursive function to traverse all the routes in the board that the horse can go to return to its starting position.
  16. void traverse_routes(int* chessboard, int m, int n, 
  17.                      int start_m, int start_n, int curr_m, int curr_n, 
  18.                      vector<pair<intint>* >* route, vector<vector<pair<intint>* >* >* routes) {
  19.     int next_m, next_n;
  20.     *(chessboard + curr_m * n + curr_n) = 1; // The horse has been in this current position.
  21.     route->push_back(new pair<intint>(curr_m, curr_n));
  22.     for(int i = 0; i < NUMBER_OF_DIRECTIONS; ++i) { // Try every direction the horse can move.
  23.         next_m = curr_m + direction[0][i];
  24.         next_n = curr_n + direction[1][i];
  25.         if(in_board(m, n, next_m, next_n) && *(chessboard + next_m * n + next_n) == 0) { // If next position is in the board.
  26.             traverse_routes(chessboard, m, n, start_m, start_n, next_m, next_n, route, routes); // Go to that position can recursively traverse from that position.
  27.         }
  28.         else if(next_m == start_m && next_n == start_n) { // If next position is the starting position.
  29.             //++number_of_routes; // One route is found.
  30.             routes->push_back(new vector<pair<intint>* >(*route));
  31.         }
  32.     }
  33.     *(chessboard + curr_m * n + curr_n) = 0; // The horse has not been in this current position.
  34.     route->pop_back();
  35. }
  36. // A wrapper method for the horse route traversal problem.
  37. vector<vector<pair<intint>* >* >* horse_route_traversal(int m, int n, int start_m, int start_n) {
  38.     int* chessboard, number_of_routes;
  39.     vector<pair<intint>* >* route;
  40.     vector<vector<pair<intint>* >* >* routes;
  41.     // Initialization of the auxiliary memory.
  42.     chessboard = new int[m*n];
  43.     memset(chessboard, 0, m*n*sizeof(int));
  44.     route = new vector<pair<intint>* >;
  45.     routes = new vector<vector<pair<intint>* >* >;
  46.     // Call the recursive function.
  47.     traverse_routes(chessboard, m, n, start_m, start_n, start_m, start_n, route, routes);
  48.     // Free dynamic-allocated memory.
  49.     delete[] chessboard;
  50.     delete route;
  51.     return routes;
  52. }
  53. // Write one route to file.
  54. void save_route(ofstream& ofs, vector<pair<intint>* >* route) {
  55.     vector<pair<intint>* >::iterator iter, end;
  56.     for(iter = route->begin(), end = route->end(); iter != end; ++iter) {
  57.         ofs << "(" << (*iter)->first << "," << (*iter)->second << ") -> ";
  58.     }
  59.     ofs << "(" << (*route->begin())->first << "," << (*route->begin())->second << ")" << endl;
  60. }
  61. // Write all the routes to file.
  62. void save_routes(const char* file_name, vector<vector<pair<intint>* >* >* routes) {
  63.     ofstream ofs(file_name);
  64.     if(routes->empty()) { // No route found.
  65.         ofs << "No route found." << endl;
  66.         cout << "Saved successfully." << endl;
  67.         return;
  68.     }
  69.     vector<vector<pair<intint>* >* >::iterator iter, end;
  70.     for(iter = routes->begin(), end = routes->end(); iter != end; ++iter) { // Iterate every route.
  71.         save_route(ofs, *iter);
  72.     }
  73.     ofs << endl;
  74.     cout << "Saved successfully." << endl;
  75. }
  76. int main() {
  77.     int m, n, start_m, start_n;
  78.     vector<vector<pair<intint>* >* >* routes;
  79.     
  80.     // Input the parameters.
  81.     cout << "Input the size of chessboard (m n):" << endl;
  82.     cin >> m >> n;
  83.     while(!(m > 0 && n > 0)) {
  84.         cout << "m and n should be positive both." << endl;
  85.         cin >> m >> n;
  86.     }
  87.     cout << "Input the starting position of the horse (start_m start_n):" << endl;
  88.     cin >> start_m >> start_n;
  89.     while(!in_board(m, n, start_m, start_n)) {
  90.         cout << "start_m and start_n should be in [0, m) and [0, n) repectively." << endl;
  91.         cin >> start_m >> start_n;
  92.     }
  93.     
  94.     // Get the total number of the horse routes.
  95.     routes = horse_route_traversal(m, n, start_m, start_n);
  96.     save_routes("Horse.txt", routes);
  97.     
  98.     return 0;
  99. }

When executing the new program, we still input the board's size as 4*5 and the starting position as (0,0). Here is the first line of the file storing the routes, i.e., the first possible route for the horse to move and return:

(0,0) -> (2,1) -> (1,3) -> (0,1) -> (2,2) -> (1,0) -> (0,2) -> (2,3) -> (1,1) -> (0,3) -> (2,4) -> (1,2) -> (0,0)

And there are 1508 lines in the file. If we set the board's size as 4*5 and the starting position as (1,1), then the first line of the file is:

(1,1) -> (0,3) -> (2,4) -> (1,2) -> (0,0) -> (2,1) -> (1,3) -> (0,1) -> (2,2) -> (1,0) -> (0,2) -> (2,3) -> (1,1)

And there are 4596 lines in the new file.

The starting configuration of this puzzle is a row of cells, with disks located on cells through . The goal is to move the disks to the end of the row using a constrained set of actions. At each step, a disk can only be moved to an adjacent empty cell, or to an empty cell two spaces away if another disk is located on the intervening square. Given these restrictions, it can be seen that in many cases, no movements will be possible for the majority of the disks. For example, from the starting position, the only two options are to move the last disk from cell to cell , or to move the second-to-last disk from cell to cell . 1. [15 points] Write a function solve_identical_disks(length, n) that returns an optimal solution to the above problem as a list of moves, where length is the number of cells in the row and n is the number of disks. Each move in the solution should be a twoelement tuple of the form (from, to) indicating a disk movement from the cell from to the cell to. As suggested by its name, this function should treat all disks as being identical. Your solver for this problem should be implemented using a breadth-first graph search. The exact solution produced is not important, as long as it is of minimal length. Unlike in the previous two sections, no requirement is made with regards to the manner in which puzzle configurations are represented. Before you begin, think carefully about which data structures might be best suited for the problem, as this choice may affect the efficiency of your search
最新发布
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值