Advertisement
alexbuisson

TreasureHunter

Nov 6th, 2013
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.88 KB | None | 0 0
  1. // TreasureHunter.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include <iostream>
  5. #include <fstream>
  6. #include <vector>
  7. #include <utility>
  8. #include <deque>
  9. #include <algorithm>
  10. #include <iterator>
  11. #include <set>
  12. #include <cfloat>
  13.  
  14. #include <assert.h>
  15.  
  16. using namespace std;
  17.  
  18.  
  19. // disable warning that debugging information has lines that are truncated
  20. // occurs in stl headers
  21. #pragma warning( disable : 4786 )
  22.  
  23. template <class T> class AStarState;
  24.  
  25. // The AStar search class. UserState is the users state space type
  26. template <class UserState> class AStarSearch
  27. {
  28. public: // data
  29.     enum
  30.     {
  31.         SEARCH_STATE_NOT_INITIALISED,
  32.         SEARCH_STATE_SEARCHING,
  33.         SEARCH_STATE_SUCCEEDED,
  34.         SEARCH_STATE_FAILED,
  35.         SEARCH_STATE_OUT_OF_MEMORY,
  36.         SEARCH_STATE_INVALID
  37.     };
  38.  
  39.  
  40.     // A node represents a possible state in the search
  41.     // The user provided state type is included inside this type
  42. public:
  43.  
  44.     class Node
  45.     {
  46.     public:
  47.  
  48.         Node *parent; // used during the search to record the parent of successor nodes
  49.         Node *child; // used after the search for the application to view the search in reverse
  50.         UserState m_UserState;
  51.  
  52.         float g; // cost of this node + it's predecessors
  53.         float h; // heuristic estimate of distance to goal
  54.         float f; // sum of cumulative cost of predecessors and self and heuristic
  55.  
  56.         Node() :
  57.             parent(0),
  58.             child(0),
  59.             g(0.0f),
  60.             h(0.0f),
  61.             f(0.0f)
  62.         {}
  63.     };
  64.  
  65.  
  66.     // For sorting the heap the STL needs compare function that lets us compare
  67.     // the f value of two nodes
  68.     class HeapCompare_f
  69.     {
  70.     public:
  71.         bool operator() (const Node *x, const Node *y) const { return x->f > y->f; }
  72.     };
  73.  
  74. public: // methods
  75.     // constructor just initialises private data
  76.     AStarSearch() :
  77.         m_AllocateNodeCount(0),
  78.         m_State(SEARCH_STATE_NOT_INITIALISED),
  79.         m_CurrentSolutionNode(NULL),
  80.         m_CancelRequest(false)
  81.     {}
  82.  
  83.     AStarSearch(int MaxNodes) :
  84.         m_AllocateNodeCount(0),
  85.         m_State(SEARCH_STATE_NOT_INITIALISED),
  86.         m_CurrentSolutionNode(NULL),
  87.         m_CancelRequest(false)
  88.     {}
  89.  
  90.     // call at any time to cancel the search and free up all the memory
  91.     void CancelSearch() { m_CancelRequest = true; }
  92.  
  93.     // Set Start and goal states
  94.     void SetStartAndGoalStates(UserState Start, UserState Goal)
  95.     {
  96.         m_CancelRequest = false;
  97.         m_Start = AllocateNode();
  98.         m_Goal = AllocateNode();
  99.         assert((m_Start != NULL && m_Goal != NULL)); //THROW
  100.         m_Start->m_UserState = Start;
  101.         m_Goal->m_UserState = Goal;
  102.         m_State = SEARCH_STATE_SEARCHING;
  103.         // Initialise the AStar specific parts of the Start Node
  104.         // The user only needs fill out the state information
  105.         m_Start->g = 0;
  106.         m_Start->h = m_Start->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
  107.         m_Start->f = m_Start->g + m_Start->h;
  108.         m_Start->parent = 0;
  109.         // Push the start node on the Open list
  110.         m_OpenList.push_back(m_Start); // heap now unsorted
  111.         // Sort back element into heap
  112.         push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
  113.         // Initialise counter for search steps
  114.         m_Steps = 0;
  115.     }
  116.  
  117.     // Advances search one step
  118.     unsigned int SearchStep()
  119.     {
  120.         // Firstly break if the user has not initialised the search
  121.         assert((m_State > SEARCH_STATE_NOT_INITIALISED) && (m_State < SEARCH_STATE_INVALID)); //THROW
  122.         // Next I want it to be safe to do a searchstep once the search has succeeded...
  123.         if ((m_State == SEARCH_STATE_SUCCEEDED) || (m_State == SEARCH_STATE_FAILED)) {
  124.             return m_State;
  125.         }
  126.         // Failure is defined as emptying the open list as there is nothing left to
  127.         // search...
  128.         // New: Allow user abort
  129.         if (m_OpenList.empty() || m_CancelRequest) {
  130.             FreeAllNodes();
  131.             m_State = SEARCH_STATE_FAILED;
  132.             return m_State;
  133.         }
  134.         // Incremement step count
  135.         m_Steps++;
  136.         // Pop the best node (the one with the lowest f)
  137.         Node *n = m_OpenList.front(); // get pointer to the node
  138.         pop_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
  139.         m_OpenList.pop_back();
  140.         // Check for the goal, once we pop that we're done
  141.         if (n->m_UserState.IsGoal(m_Goal->m_UserState))
  142.         {
  143.             // The user is going to use the Goal Node he passed in
  144.             // so copy the parent pointer of n
  145.             m_Goal->parent = n->parent;
  146.             m_Goal->g = n->g;
  147.  
  148.             // A special case is that the goal was passed in as the start state
  149.             // so handle that here
  150.             if (false == n->m_UserState.IsSameState(m_Start->m_UserState)) {
  151.                 FreeNode(n);
  152.                 // set the child pointers in each node (except Goal which has no child)
  153.                 Node *nodeChild = m_Goal;
  154.                 Node *nodeParent = m_Goal->parent;
  155.                 do              {
  156.                     nodeParent->child = nodeChild;
  157.                     nodeChild = nodeParent;
  158.                     nodeParent = nodeParent->parent;
  159.                 } while (nodeChild != m_Start); // Start is always the first node by definition
  160.             }
  161.             // delete nodes that aren't needed for the solution
  162.             FreeUnusedNodes();
  163.             m_State = SEARCH_STATE_SUCCEEDED;
  164.             return m_State;
  165.         }
  166.         else // not goal
  167.         {
  168.             // We now need to generate the successors of this node
  169.             // The user helps us to do this, and we keep the new nodes in
  170.             // m_Successors ...
  171.             m_Successors.clear(); // empty vector of successor nodes to n
  172.             // User provides this functions and uses AddSuccessor to add each successor of
  173.             // node 'n' to m_Successors
  174.             bool ret = n->m_UserState.GetSuccessors(this, n->parent ? &n->parent->m_UserState : NULL);
  175.             if (!ret)
  176.             {
  177.                 typename vector< Node * >::iterator successor;
  178.                 // free the nodes that may previously have been added
  179.                 for (successor = m_Successors.begin(); successor != m_Successors.end(); successor++) {
  180.                     FreeNode((*successor));
  181.                 }
  182.                 m_Successors.clear(); // empty vector of successor nodes to n
  183.                 // free up everything else we allocated
  184.                 FreeAllNodes();
  185.                 m_State = SEARCH_STATE_OUT_OF_MEMORY;
  186.                 return m_State;
  187.             }
  188.  
  189.             // Now handle each successor to the current node ...
  190.             for (typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor++) {
  191.                 //  The g value for this successor ...
  192.                 float newg = n->g + n->m_UserState.GetCost((*successor)->m_UserState);
  193.                 // Now we need to find whether the node is on the open or closed lists
  194.                 // If it is but the node that is already on them is better (lower g)
  195.                 // then we can forget about this successor
  196.  
  197.                 // First linear search of open list to find node
  198.                 typename vector< Node * >::iterator openlist_result;
  199.                 for (openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result++) {
  200.                     if ((*openlist_result)->m_UserState.IsSameState((*successor)->m_UserState)) {
  201.                         break;
  202.                     }
  203.                 }
  204.                 if (openlist_result != m_OpenList.end())
  205.                 {
  206.                     // we found this state on open
  207.                     if ((*openlist_result)->g <= newg) {
  208.                         FreeNode((*successor));
  209.                         // the one on Open is cheaper than this one
  210.                         continue;
  211.                     }
  212.                 }
  213.  
  214.                 typename vector< Node * >::iterator closedlist_result;
  215.                 for (closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result++) {
  216.                     if ((*closedlist_result)->m_UserState.IsSameState((*successor)->m_UserState)) {
  217.                         break;
  218.                     }
  219.                 }
  220.  
  221.                 if (closedlist_result != m_ClosedList.end())
  222.                 {
  223.                     // we found this state on closed
  224.                     if ((*closedlist_result)->g <= newg) {
  225.                         // the one on Closed is cheaper than this one
  226.                         FreeNode((*successor));
  227.                         continue;
  228.                     }
  229.                 }
  230.  
  231.                 // This node is the best node so far with this particular state
  232.                 // so lets keep it and set up its AStar specific data ...
  233.  
  234.                 (*successor)->parent = n;
  235.                 (*successor)->g = newg;
  236.                 (*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
  237.                 (*successor)->f = (*successor)->g + (*successor)->h;
  238.  
  239.                 // Remove successor from closed if it was on it
  240.                 if (closedlist_result != m_ClosedList.end()) {
  241.                     // remove it from Closed
  242.                     FreeNode((*closedlist_result));
  243.                     m_ClosedList.erase(closedlist_result);
  244.                     // Fix thanks to ...
  245.                     // Greg Douglas <gregdouglasmail@gmail.com>
  246.                     // who noticed that this code path was incorrect
  247.                     // Here we have found a new state which is already CLOSED
  248.                     // anus
  249.                 }
  250.  
  251.                 // Update old version of this node
  252.                 if (openlist_result != m_OpenList.end()) {
  253.                     FreeNode((*openlist_result));
  254.                     m_OpenList.erase(openlist_result);
  255.  
  256.                     // re-make the heap
  257.                     // make_heap rather than sort_heap is an essential bug fix
  258.                     // thanks to Mike Ryynanen for pointing this out and then explaining
  259.                     // it in detail. sort_heap called on an invalid heap does not work
  260.                     make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
  261.                 }
  262.  
  263.                 // heap now unsorted
  264.                 m_OpenList.push_back((*successor));
  265.                 // sort back element into heap
  266.                 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
  267.             }
  268.             // push n onto Closed, as we have expanded it now
  269.             m_ClosedList.push_back(n);
  270.         } // end else (not goal so expand)
  271.  
  272.         return m_State; // Succeeded bool is false at this point.
  273.  
  274.     }
  275.  
  276.     // User calls this to add a successor to a list of successors
  277.     // when expanding the search frontier
  278.     bool AddSuccessor(UserState State)
  279.     {
  280.         Node *node = AllocateNode();
  281.         if (node) {
  282.             node->m_UserState = State;
  283.             m_Successors.push_back(node);
  284.             return true;
  285.         }
  286.         return false;
  287.     }
  288.  
  289.     // Free the solution nodes
  290.     // This is done to clean up all used Node memory when you are done with the
  291.     // search
  292.     void FreeSolutionNodes()
  293.     {
  294.         Node *n = m_Start;
  295.         if (m_Start->child)
  296.         {
  297.             do
  298.             {
  299.                 Node *del = n;
  300.                 n = n->child;
  301.                 FreeNode(del);
  302.                 del = nullptr;
  303.             } while (n != m_Goal);
  304.  
  305.             FreeNode(n); // Delete the goal
  306.         }
  307.         else
  308.         {
  309.             // if the start node is the solution we need to just delete the start and goal
  310.             // nodes
  311.             FreeNode(m_Start);
  312.             FreeNode(m_Goal);
  313.         }
  314.  
  315.     }
  316.  
  317.     unsigned int SearchSolution(unsigned int& nbStep, std::vector<UserState>& solution)
  318.     {
  319.         unsigned int SearchState;
  320.         unsigned int SearchSteps = 0;
  321.  
  322.         do
  323.         {
  324.             SearchState = SearchStep();
  325.             SearchSteps++;
  326.             /*cout << "Steps:" << SearchSteps << "\n";
  327.             int len = 0;
  328.             cout << "Open:\n";
  329.             UserState *p = GetOpenListStart();
  330.             while (p)
  331.             {
  332.             len++;
  333.             p = GetOpenListNext();
  334.  
  335.             }
  336.             cout << "Open list has " << len << " nodes\n";
  337.             len = 0;
  338.             cout << "Closed:\n";
  339.             p = GetClosedListStart();
  340.             while (p)
  341.             {
  342.             len++;
  343.             p = GetClosedListNext();
  344.             }
  345.             cout << "Closed list has " << len << " nodes\n";
  346.             //*/
  347.         } while (SearchState == AStarSearch<UserState>::SEARCH_STATE_SEARCHING);
  348.  
  349.         solution.clear();
  350.         if (SearchState == AStarSearch<UserState>::SEARCH_STATE_SUCCEEDED)
  351.         {
  352.             //cout << "Search found goal state\n";
  353.             UserState *node = GetSolutionStart();
  354.             int steps = 0;
  355.             solution.push_back(*node);
  356.             for (;;)
  357.             {
  358.                 node = GetSolutionNext();
  359.                 if (!node) {
  360.                     break;
  361.                 }
  362.                 solution.push_back(*node);
  363.                 steps++;
  364.             };
  365.             //cout << "Solution steps " << steps << endl;
  366.             // Once you're done with the solution you can free the nodes up
  367.             FreeSolutionNodes();
  368.         }
  369.         else if (SearchState == AStarSearch<UserState>::SEARCH_STATE_FAILED)
  370.         {
  371.             //cout << "Search terminated. Did not find goal state\n";
  372.         }
  373.  
  374.         nbStep = SearchSteps;
  375.  
  376.         return SearchState;
  377.     }
  378.  
  379.  
  380.     // Functions for traversing the solution
  381.  
  382.     // Get start node
  383.     UserState *GetSolutionStart()
  384.     {
  385.         m_CurrentSolutionNode = m_Start;
  386.         if (m_Start)
  387.         {
  388.             return &m_Start->m_UserState;
  389.         }
  390.         else
  391.         {
  392.             return nullptr;
  393.         }
  394.     }
  395.  
  396.     // Get next node
  397.     UserState *GetSolutionNext()
  398.     {
  399.         if (m_CurrentSolutionNode)
  400.         {
  401.             if (m_CurrentSolutionNode->child)
  402.             {
  403.                 Node *child = m_CurrentSolutionNode->child;
  404.                 m_CurrentSolutionNode = m_CurrentSolutionNode->child;
  405.                 return &child->m_UserState;
  406.             }
  407.         }
  408.         return nullptr;
  409.     }
  410.  
  411.     // Get end node
  412.     UserState *GetSolutionEnd()
  413.     {
  414.         m_CurrentSolutionNode = m_Goal;
  415.         if (m_Goal) {
  416.             return &m_Goal->m_UserState;
  417.         }
  418.         else {
  419.             return nullptr;
  420.         }
  421.     }
  422.  
  423.     // Step solution iterator backwards
  424.     UserState *GetSolutionPrev()
  425.     {
  426.         if (m_CurrentSolutionNode)
  427.         {
  428.             if (m_CurrentSolutionNode->parent)
  429.             {
  430.                 Node *parent = m_CurrentSolutionNode->parent;
  431.                 m_CurrentSolutionNode = m_CurrentSolutionNode->parent;
  432.                 return &parent->m_UserState;
  433.             }
  434.         }
  435.         return nullptr;
  436.     }
  437.  
  438.     // Get final cost of solution
  439.     // Returns FLT_MAX if goal is not defined or there is no solution
  440.     float GetSolutionCost()
  441.     {
  442.         if (m_Goal && m_State == SEARCH_STATE_SUCCEEDED)
  443.         {
  444.             return m_Goal->g;
  445.         }
  446.         else
  447.         {
  448.             return FLT_MAX;
  449.         }
  450.     }
  451.  
  452.     // For educational use and debugging it is useful to be able to view
  453.     // the open and closed list at each step, here are two functions to allow that.
  454.  
  455.     UserState *GetOpenListStart()
  456.     {
  457.         float f, g, h;
  458.         return GetOpenListStart(f, g, h);
  459.     }
  460.  
  461.     UserState *GetOpenListStart(float &f, float &g, float &h)
  462.     {
  463.         iterDbgOpen = m_OpenList.begin();
  464.         if (iterDbgOpen != m_OpenList.end())
  465.         {
  466.             f = (*iterDbgOpen)->f;
  467.             g = (*iterDbgOpen)->g;
  468.             h = (*iterDbgOpen)->h;
  469.             return &(*iterDbgOpen)->m_UserState;
  470.         }
  471.  
  472.         return nullptr;
  473.     }
  474.  
  475.     UserState *GetOpenListNext()
  476.     {
  477.         float f, g, h;
  478.         return GetOpenListNext(f, g, h);
  479.     }
  480.  
  481.     UserState *GetOpenListNext(float &f, float &g, float &h)
  482.     {
  483.         iterDbgOpen++;
  484.         if (iterDbgOpen != m_OpenList.end())
  485.         {
  486.             f = (*iterDbgOpen)->f;
  487.             g = (*iterDbgOpen)->g;
  488.             h = (*iterDbgOpen)->h;
  489.             return &(*iterDbgOpen)->m_UserState;
  490.         }
  491.  
  492.         return nullptr;
  493.     }
  494.  
  495.     UserState *GetClosedListStart()
  496.     {
  497.         float f, g, h;
  498.         return GetClosedListStart(f, g, h);
  499.     }
  500.  
  501.     UserState *GetClosedListStart(float &f, float &g, float &h)
  502.     {
  503.         iterDbgClosed = m_ClosedList.begin();
  504.         if (iterDbgClosed != m_ClosedList.end())
  505.         {
  506.             f = (*iterDbgClosed)->f;
  507.             g = (*iterDbgClosed)->g;
  508.             h = (*iterDbgClosed)->h;
  509.  
  510.             return &(*iterDbgClosed)->m_UserState;
  511.         }
  512.  
  513.         return nullptr;
  514.     }
  515.  
  516.     UserState *GetClosedListNext()
  517.     {
  518.         float f, g, h;
  519.         return GetClosedListNext(f, g, h);
  520.     }
  521.  
  522.     UserState *GetClosedListNext(float &f, float &g, float &h)
  523.     {
  524.         iterDbgClosed++;
  525.         if (iterDbgClosed != m_ClosedList.end())
  526.         {
  527.             f = (*iterDbgClosed)->f;
  528.             g = (*iterDbgClosed)->g;
  529.             h = (*iterDbgClosed)->h;
  530.  
  531.             return &(*iterDbgClosed)->m_UserState;
  532.         }
  533.  
  534.         return nullptr;
  535.     }
  536.  
  537.     // Get the number of steps
  538.  
  539.     int GetStepCount() { return m_Steps; }
  540.  
  541.     void EnsureMemoryFreed()
  542.     {}
  543.  
  544. private: // methods
  545.  
  546.     // This is called when a search fails or is cancelled to free all used
  547.     // memory
  548.     void FreeAllNodes()
  549.     {
  550.         // iterate open list and delete all nodes
  551.         typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
  552.  
  553.         while (iterOpen != m_OpenList.end())
  554.         {
  555.             Node *n = (*iterOpen);
  556.             FreeNode(n);
  557.             iterOpen++;
  558.         }
  559.         m_OpenList.clear();
  560.         // iterate closed list and delete unused nodes
  561.         typename vector< Node * >::iterator iterClosed;
  562.         for (iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed++)
  563.         {
  564.             Node *n = (*iterClosed);
  565.             FreeNode(n);
  566.         }
  567.         m_ClosedList.clear();
  568.         // delete the goal
  569.         FreeNode(m_Goal);
  570.     }
  571.  
  572.  
  573.     // This call is made by the search class when the search ends. A lot of nodes may be
  574.     // created that are still present when the search ends. They will be deleted by this
  575.     // routine once the search ends
  576.     void FreeUnusedNodes()
  577.     {
  578.         // iterate open list and delete unused nodes
  579.         typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
  580.         while (iterOpen != m_OpenList.end())
  581.         {
  582.             Node *n = (*iterOpen);
  583.             if (!n->child)
  584.             {
  585.                 FreeNode(n);
  586.                 n = nullptr;
  587.             }
  588.             iterOpen++;
  589.         }
  590.         m_OpenList.clear();
  591.         // iterate closed list and delete unused nodes
  592.         typename vector< Node * >::iterator iterClosed;
  593.         for (iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed++)
  594.         {
  595.             Node *n = (*iterClosed);
  596.             if (!n->child)
  597.             {
  598.                 FreeNode(n);
  599.                 n = nullptr;
  600.             }
  601.         }
  602.         m_ClosedList.clear();
  603.     }
  604.  
  605.     // Node memory management
  606.     Node *AllocateNode()
  607.     {
  608.         Node *p = new Node;
  609.         return p;
  610.     }
  611.  
  612.     void FreeNode(Node *node)
  613.     {
  614.         m_AllocateNodeCount--;
  615.         delete node;
  616.     }
  617.  
  618. private: // data
  619.  
  620.     // Heap (simple vector but used as a heap, cf. Steve Rabin's game gems article)
  621.     vector< Node *> m_OpenList;
  622.     // Closed list is a vector.
  623.     vector< Node * > m_ClosedList;
  624.     // Successors is a vector filled out by the user each type successors to a node
  625.     // are generated
  626.     vector< Node * > m_Successors;
  627.     // State
  628.     unsigned int m_State;
  629.     // Counts steps
  630.     int m_Steps;
  631.     // Start and goal state pointers
  632.     Node *m_Start;
  633.     Node *m_Goal;
  634.     // Node list
  635.     Node *m_CurrentSolutionNode;
  636.  
  637.     //Debug : need to keep these two iterators around
  638.     // for the user Dbg functions
  639.     typename vector< Node * >::iterator iterDbgOpen;
  640.     typename vector< Node * >::iterator iterDbgClosed;
  641.     // debugging : count memory allocation and free's
  642.     int m_AllocateNodeCount;
  643.  
  644.     //To Stop the search loop .... When it will be inside ...
  645.     bool m_CancelRequest;
  646. };
  647.  
  648. template <class T> class AStarState
  649. {
  650. public:
  651.     virtual ~AStarState() {}
  652.     virtual float GoalDistanceEstimate(T &nodeGoal) = 0; // Heuristic function which computes the estimated cost to the goal node
  653.     virtual bool IsGoal(T &nodeGoal) = 0; // Returns true if this node is the goal node
  654.     virtual bool GetSuccessors(AStarSearch<T> *astarsearch, T *parent_node) = 0; // Retrieves all successors to this node and adds them via astarsearch.addSuccessor()
  655.     virtual float GetCost(T &successor) = 0; // Computes the cost of travelling from this node to the successor node
  656.     virtual bool IsSameState(T &rhs) = 0; // Returns true if this node is the same as the rhs node
  657. };
  658.  
  659.  
  660. typedef vector<vector<char>> maze_t;
  661.  
  662. int fact(int i)
  663. {
  664.     if (i == 1)
  665.         return i;
  666.     else
  667.         return i * fact(i - 1);
  668. }
  669.  
  670. struct testcase_t
  671. {
  672.     int num;
  673.     maze_t maze;
  674.     int earliestTime; //-1 if no solution
  675.     int expectedResult;
  676.  
  677.     testcase_t() { num = 0; earliestTime = -1; expectedResult = -1; }
  678.  
  679.  
  680.     void printMaze()
  681.     {
  682.         cout << "Maze Number " << num << endl;
  683.         cout << "Maze " << maze.size() << "x" << maze.size() << endl;
  684.         cout << "Expected result " << expectedResult << endl;
  685.         for (auto &row : maze) {
  686.             for (auto &c : row) {
  687.                 cout << c << " ";
  688.             }
  689.             cout << endl;
  690.         }
  691.     }
  692.  
  693.     void printResult()
  694.     {
  695.         //cout << "Result " << earliestTime << ((expectedResult == earliestTime) ? " Success !!!! " : ((expectedResult < earliestTime) ? " Failure expected time smaller " : " Failure expected time bigger ")) << endl;
  696.         cout << earliestTime << endl;
  697.     }
  698.  
  699.     struct pos_t {
  700.         int x; int y;
  701.         pos_t(){ x = 0; y = 0; }
  702.         pos_t(int X, int Y){ x = X; y = Y; }
  703.         pos_t(pos_t const & r) { x = r.x; y = r.y; }
  704.         pos_t& operator=(pos_t const & r) { x = r.x; y = r.y; return *this; }
  705.         bool operator==(pos_t const & r) { return x == r.x && y == r.y; }
  706.         bool operator < (pos_t const & p) const
  707.         {
  708.             return (x < p.x) || ((x == p.x) && (y < p.y));
  709.         }
  710.         friend ostream& operator << (ostream &o, const pos_t& p)
  711.         {
  712.             return o << "(" << p.x << "," << p.y << ")";
  713.         }
  714.  
  715.         bool isIn(maze_t const & m) { return x >= 0 && x < (int)(m.size()) && y >= 0 && y < (int)(m.size()); }
  716.         bool isAvailable(maze_t const & m) { return m[x][y] != *("#"); }
  717.         unsigned int ManhattanDistanceTo(pos_t const &p) { return (unsigned int)(abs(x - p.x) + abs(y - p.y)); }
  718.         vector<pos_t> GetCanditate(maze_t const & m)
  719.         {
  720.             vector<pos_t> c = { pos_t(x - 1, y), pos_t(x, y - 1), pos_t(x + 1, y), pos_t(x, y + 1) };
  721.             auto it = begin(c);
  722.             while (it != end(c)) {
  723.                 if (!(*it).isIn(m) || !(*it).isAvailable(m)){
  724.                     it = c.erase(it);
  725.                 }
  726.                 else {
  727.                     ++it;
  728.                 }
  729.             }
  730.             return c;
  731.         }
  732.     };
  733.  
  734.     struct search_state_t
  735.     {
  736.         pos_t _curr;
  737.         const maze_t * _maze_ref;
  738.  
  739.         search_state_t() : _curr(), _maze_ref(nullptr) {}
  740.         search_state_t(const pos_t& p, const maze_t * m) :_curr(p), _maze_ref(m){}
  741.         search_state_t(search_state_t const & r) { _curr = r._curr; _maze_ref = r._maze_ref; }
  742.         search_state_t& operator=(search_state_t const & r) { _curr = r._curr; _maze_ref = r._maze_ref; return *this; }
  743.  
  744.         float GoalDistanceEstimate(search_state_t &nodeGoal)
  745.         {
  746.             return (float)(_curr.ManhattanDistanceTo(nodeGoal._curr));
  747.         }
  748.         bool IsGoal(search_state_t &nodeGoal)
  749.         {
  750.             return _curr == nodeGoal._curr;
  751.         }
  752.         bool GetSuccessors(AStarSearch<search_state_t> *astarsearch, search_state_t *parent_node)
  753.         {
  754.             auto c = _curr.GetCanditate(*_maze_ref);
  755.             auto it = begin(c);
  756.             while (it != end(c)) {
  757.                 if (parent_node != nullptr && (*it) == parent_node->_curr){
  758.                     it = c.erase(it);
  759.                 }
  760.                 else {
  761.                     astarsearch->AddSuccessor(search_state_t(*it, _maze_ref));
  762.                     ++it;
  763.                 }
  764.             }
  765.             return true;
  766.         }
  767.         float GetCost(search_state_t &successor)
  768.         {
  769.             return 1.0;
  770.         }
  771.         bool IsSameState(search_state_t &rhs)
  772.         {
  773.             return _curr == rhs._curr;
  774.         }
  775.  
  776.     };
  777.  
  778.     void solve()
  779.     {
  780.         //cout << "Enter solve for maze " << maze.size() << "x" << maze.size() << endl;
  781.         vector<pos_t> treasurePos;
  782.         for (auto i = 0u; i < maze.size(); ++i)
  783.         {
  784.             for (auto j = 0u; j < maze[i].size(); ++j)
  785.             {
  786.                 if (maze[i][j] == *("*"))
  787.                     treasurePos.push_back(pos_t(i, j));
  788.             }
  789.         }
  790.  
  791.         deque<vector<pos_t>> treasure_order;
  792.         std::sort(begin(treasurePos), end(treasurePos));
  793.         do {
  794.             vector<pos_t> c;
  795.  
  796.             c.push_back(pos_t(0, 0));
  797.             copy(begin(treasurePos), end(treasurePos), back_inserter(c));
  798.             c.push_back(pos_t(maze.size() - 1, maze.size() - 1));
  799.  
  800.             /*copy(begin(c), end(c), ostream_iterator<pos_t>(cout, " -> "));
  801.             cout << endl;//*/
  802.             treasure_order.push_back(c);
  803.  
  804.         } while (std::next_permutation(begin(treasurePos), end(treasurePos)));//*/
  805.         //cout << "we stored " << treasure_order.size() << " path to get all the treasure (=nbTreasure! = " << fact((int)treasurePos.size()) << ")" << endl;
  806.  
  807.         vector<vector<pair<pos_t, pos_t>>> allCandidatePath;
  808.         for (auto &p : treasure_order)
  809.         {
  810.             vector<pair<pos_t, pos_t>> candidatePath;
  811.             for (auto b = begin(p); b < end(p) - 1; ++b)
  812.             {
  813.                 candidatePath.push_back(make_pair(*b, *(b + 1)));
  814.             }
  815.             allCandidatePath.push_back(candidatePath);
  816.         }
  817.  
  818.         /*for_each(begin(allCandidatePath), end(allCandidatePath),
  819.             [](vector<pair<pos_t, pos_t>> const & p)
  820.             {
  821.             for_each(begin(p), end(p), [](pair<pos_t, pos_t> const & j)
  822.             {
  823.             cout << j.first << "->" << j.second;
  824.             });
  825.             cout << endl;
  826.             });*/
  827.         int minPath = std::numeric_limits<int>::max();
  828.         for (auto &p : allCandidatePath)
  829.         {
  830.             int minPathCandidate = 0;
  831.             //if A* path from b.first to b.second exist
  832.             // store path lenght and next tuple.
  833.             //else
  834.             // mark that path as invalid and continue with nex candidate path...
  835.             auto it = begin(p);
  836.             while (it != end(p))
  837.             {
  838.                 auto checkpath = [this, &minPathCandidate](pair<pos_t, pos_t> const & j)
  839.                 {
  840.                     //cout << "Search A* from " << j.first << " to " << j.second << std::endl;
  841.                     AStarSearch<search_state_t> astarsearch;
  842.                     astarsearch.SetStartAndGoalStates(search_state_t(j.first, &(this->maze)), search_state_t(j.second, &(this->maze)));
  843.                     std::vector<search_state_t> path;
  844.                     unsigned int nb_step;
  845.                     auto res = astarsearch.SearchSolution(nb_step, path);
  846.                     if (res == AStarSearch<search_state_t>::SEARCH_STATE_SUCCEEDED) {
  847.                         /*std::cout << "Found with " << nb_step << " step a path of " << path.size() << std::endl;
  848.                         for (const auto& s : path){
  849.                             std::cout << s._curr << " -> ";
  850.                         }
  851.                         std::cout << std::endl;//*/
  852.                         minPathCandidate += path.size() - 1;
  853.                     }
  854.                     else {
  855.                         //std::cout << "No solution with " << std::endl;
  856.                         minPathCandidate = 0;
  857.                     }
  858.                     astarsearch.EnsureMemoryFreed();
  859.                 };
  860.  
  861.                 checkpath(*it);
  862.                 if (minPathCandidate == 0)
  863.                     break;
  864.  
  865.                 it++;
  866.             }
  867.  
  868.             //if path is success get its total length and store it
  869.             if (minPathCandidate != 0)
  870.             {
  871.                 minPath = std::min(minPath, minPathCandidate);
  872.             }
  873.         }
  874.  
  875.         //Get Min Length and Min index.
  876.         //Display Minimal Path and duration !
  877.         this->earliestTime = ((minPath != std::numeric_limits<int>::max()) ? minPath : -1);
  878.         /*cout << "**************************************\n";
  879.         cout << "Min Path = " <<  this->earliestTime << endl;
  880.         cout << "**************************************\n";*/
  881.        
  882.     }
  883. };
  884.  
  885. void LoadTestCases(istream& in, vector<testcase_t>& tests)
  886. {
  887.     int num = 0;
  888.     int nbTest = 0;
  889.     in >> nbTest;
  890.  
  891.     while (nbTest > 0)
  892.     {
  893.         int mazeSize = 0;
  894.         in >> mazeSize;
  895.         testcase_t test;
  896.         test.num = num++;
  897.         for (auto i = 0; i < mazeSize; ++i)
  898.         {
  899.             vector<char> row;
  900.             for (auto j = 0; j < mazeSize; ++j)
  901.             {
  902.                 char c;
  903.                 in >> c;
  904.                 row.push_back(c);
  905.             }
  906.             test.maze.push_back(row);
  907.         }
  908.         in >> test.expectedResult;
  909.         tests.push_back(test);
  910.  
  911.         --nbTest;
  912.     }
  913. }
  914.  
  915. int main() {
  916.     vector<testcase_t> tests;
  917.  
  918.     LoadTestCases(cin, tests);
  919.     /*ifstream testFile("testSet.txt");
  920.     LoadTestCases(testFile, tests);//*/
  921.  
  922.     for (auto test : tests)
  923.     {
  924.         //cout << "*********** test " << test.num << " *************" << endl << endl;
  925.         //test.printMaze();
  926.  
  927.         test.solve();
  928.         test.printResult();
  929.  
  930.         //cout << endl << "************************" << endl;
  931.     }
  932.  
  933.     return 0;
  934. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement