Advertisement
kartikkukreja

Water Jug Problem with BFS

Oct 11th, 2013
587
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.81 KB | None | 0 0
  1. #include <cstdio>
  2. #include <queue>
  3. #include <stack>
  4. #include <map>
  5. #include <algorithm>
  6. using namespace std;
  7.  
  8. // Representation of a state (x, y)
  9. // x and y are the amounts of water in litres in the two jugs respectively
  10. struct state {
  11.     int x, y;
  12.  
  13.     // Used by map to efficiently implement lookup of seen states
  14.     bool operator < (const state& that) const {
  15.         if (x != that.x) return x < that.x;
  16.         return y < that.y;
  17.     }
  18. };
  19.  
  20. // Capacities of the two jugs respectively and the target amount
  21. int capacity_x, capacity_y, target;
  22.  
  23. void bfs(state start, stack <pair <state, int> >& path)   {
  24.     queue <state> q;
  25.     state goal = (state) {-1, -1};
  26.  
  27.     // Stores seen states so that they are not revisited and
  28.     // maintains their parent states for finding a path through
  29.     // the state space
  30.     // Mapping from a state to its parent state and rule no. that
  31.     // led to this state
  32.     map <state, pair <state, int> > parentOf;
  33.  
  34.     q.push(start);
  35.     parentOf[start] = make_pair(start, 0);
  36.  
  37.     while (!q.empty())    {
  38.         // Get the state at the front of the queue
  39.         state top = q.front();
  40.         q.pop();
  41.  
  42.         // If the target state has been found, break
  43.         if (top.x == target || top.y == target) {
  44.             goal = top;
  45.             break;
  46.         }
  47.  
  48.         // Find the successors of this state
  49.         // This step uses production rules to prune the search space
  50.  
  51.         // Rule 1: (x, y) -> (capacity_x, y) if x < capacity_x
  52.         // Fill the first jug
  53.         if (top.x < capacity_x)  {
  54.             state child = (state) {capacity_x, top.y};
  55.             // Consider this state for visiting only if it has not been visited before
  56.             if (parentOf.find(child) == parentOf.end()) {
  57.                 q.push(child);
  58.                 parentOf[child] = make_pair(top, 1);
  59.             }
  60.         }
  61.  
  62.         // Rule 2: (x, y) -> (x, capacity_y) if y < capacity_y
  63.         // Fill the second jug
  64.         if (top.y < capacity_y)  {
  65.             state child = (state) {top.x, capacity_y};
  66.             if (parentOf.find(child) == parentOf.end()) {
  67.                 q.push(child);
  68.                 parentOf[child] = make_pair(top, 2);
  69.             }
  70.         }
  71.  
  72.         // Rule 3: (x, y) -> (0, y) if x > 0
  73.         // Empty the first jug
  74.         if (top.x > 0)  {
  75.             state child = (state) {0, top.y};
  76.             if (parentOf.find(child) == parentOf.end()) {
  77.                 q.push(child);
  78.                 parentOf[child] = make_pair(top, 3);
  79.             }
  80.         }
  81.  
  82.         // Rule 4: (x, y) -> (x, 0) if y > 0
  83.         // Empty the second jug
  84.         if (top.y > 0)  {
  85.             state child = (state) {top.x, 0};
  86.             if (parentOf.find(child) == parentOf.end()) {
  87.                 q.push(child);
  88.                 parentOf[child] = make_pair(top, 4);
  89.             }
  90.         }
  91.  
  92.         // Rule 5: (x, y) -> (min(x + y, capacity_x), max(0, x + y - capacity_x)) if y > 0
  93.         // Pour water from the second jug into the first jug until the first jug is full
  94.         // or the second jug is empty
  95.         if (top.y > 0)  {
  96.             state child = (state) {min(top.x + top.y, capacity_x), max(0, top.x + top.y - capacity_x)};
  97.             if (parentOf.find(child) == parentOf.end()) {
  98.                 q.push(child);
  99.                 parentOf[child] = make_pair(top, 5);
  100.             }
  101.         }
  102.  
  103.         // Rule 6: (x, y) -> (max(0, x + y - capacity_y), min(x + y, capacity_y)) if x > 0
  104.         // Pour water from the first jug into the second jug until the second jug is full
  105.         // or the first jug is empty
  106.         if (top.x > 0)  {
  107.             state child = (state) {max(0, top.x + top.y - capacity_y), min(top.x + top.y, capacity_y)};
  108.             if (parentOf.find(child) == parentOf.end()) {
  109.                 q.push(child);
  110.                 parentOf[child] = make_pair(top, 6);
  111.             }
  112.         }
  113.     }
  114.  
  115.     // Target state was not found
  116.     if (goal.x == -1 || goal.y == -1)
  117.         return;
  118.  
  119.     // backtrack to generate the path through the state space
  120.     path.push(make_pair(goal, 0));
  121.     // remember parentOf[start] = (start, 0)
  122.     while (parentOf[path.top().first].second != 0)
  123.         path.push(parentOf[path.top().first]);
  124. }
  125.  
  126. int main()  {
  127.     stack <pair <state, int> > path;
  128.  
  129.     printf("Enter the capacities of the two jugs : ");
  130.     scanf("%d %d", &capacity_x, &capacity_y);
  131.     printf("Enter the target amount : ");
  132.     scanf("%d", &target);
  133.  
  134.     bfs((state) {0, 0}, path);
  135.     if (path.empty())
  136.         printf("\nTarget cannot be reached.\n");
  137.     else    {
  138.         printf("\nNumber of moves to reach the target : %d\nOne path to the target is as follows :\n", path.size() - 1);
  139.         while (!path.empty())   {
  140.             state top = path.top().first;
  141.             int rule = path.top().second;
  142.             path.pop();
  143.  
  144.             switch (rule)   {
  145.                 case 0: printf("State : (%d, %d)\n#\n", top.x, top.y);
  146.                         break;
  147.                 case 1: printf("State : (%d, %d)\nAction : Fill the first jug\n", top.x, top.y);
  148.                         break;
  149.                 case 2: printf("State : (%d, %d)\nAction : Fill the second jug\n", top.x, top.y);
  150.                         break;
  151.                 case 3: printf("State : (%d, %d)\nAction : Empty the first jug\n", top.x, top.y);
  152.                         break;
  153.                 case 4: printf("State : (%d, %d)\nAction : Empty the second jug\n", top.x, top.y);
  154.                         break;
  155.                 case 5: printf("State : (%d, %d)\nAction : Pour from second jug into first jug\n", top.x, top.y);
  156.                         break;
  157.                 case 6: printf("State : (%d, %d)\nAction : Pour from first jug into second jug\n", top.x, top.y);
  158.                         break;
  159.             }
  160.         }
  161.     }
  162.  
  163.     return 0;
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement