The question is: it is legal to give you two fixed-capacity beaker with A capacity and B respectively.
1. Fill Up With A and get it from the water source
2. Full B
3. Pour A to B. After B is finished, B is full, or A is empty.
4. Pour B to A. After it is finished, A is full, or B is empty.
5. Clear
6. Clear B
The minimum steps can be obtained from the first two empty cups to obtain the water with a volume of C, where the water with a capacity of C can be placed in any container.
Sample Input
3 5 4
Sample Output
6
FILL (2)
POUR (2, 1)
DROP (1)
POUR (2, 1)
FILL (2)
POUR (2, 1)
Analysis: the classification of this question is BFS, but I haven't figured out how to BFS for a long time. I read some tips in discussion to see all the insights.
In the BFS process, the current status is two numbers: ca and cb. It indicates that there is water ca in the a beaker, And there is water cb in the B beaker.
Because there are only six options in the next step, we can enumerate all these six cases. For example, when the weights are enumerated to stepi, if the operations in this step occur, the status has been reached, we will not put the new status into the queue,
Otherwise, it is put into the queue as a new status.
We need to record the path, so we need to keep the status before each status, and also how many steps have taken to save it to the current status.
Therefore, each status has the following values:
1. Capacity of two beaker 2. Previous status 3. operation performed in the current status Step 4 to this status.
The Code is as follows:
[Cpp]
# Include <stdio. h>
# Include <memory. h>
# Define MAX_NUM 101
# Define MAX_Q MAX_NUM * MAX_NUM
Enum OPERATION
{
FILL1 = 0, FILL2, POUR12, POUR21, DROP1, DROP2, NONE
};
Struct Step
{
Int liter1;
Int liter2;
Int stepID;
OPERATION operation;
Int previous;
Step ()
{
}
Step (int l1, int l2, int step, OPERATION op, int previous)
{
Liter1 = l1;
Liter2 = l2;
StepID = step;
Operation = op;
This-> previous = previous;
}
};
Struct Queue
{
Step steps [MAX_Q];
Int front;
Int rear;
Void ini ()
{
Memset (steps, 0, sizeof (steps ));
Front = rear = 0;
}
Void push (int l1, int l2, int step, int privous, OPERATION op)
{
Steps [rear ++] = Step (l1, l2, step, op, privous );
}
};
Bool visit [MAX_NUM] [MAX_NUM];
Queue q;
Void PrintPath (int I)
{
If (I =-1)
{
Return;
}
PrintPath (q. steps [I]. previous );
Switch (q. steps [I]. operation)
{
Case FILL1:
Printf ("FILL (1) \ n ");
Break;
Case FILL2:
Printf ("FILL (2) \ n ");
Break;
Case POUR12:
Printf ("POUR (1, 2) \ n ");
Break;
Case POUR21:
Printf ("POUR (2, 1) \ n ");
Break;
Case DROP1:
Printf ("DROP (1) \ n ");
Break;
Case DROP2:
Printf ("DROP (2) \ n ");
Break;
}
}
Void BFS (int a, int B, int c)
{
Q. ini ();
Q. push (0, 0, 0,-1, NONE );
Visit [0] [0] = true;
Step nxt, current;
While (q. rear> q. front)
{
Current = q. steps [q. front ++];
If (current. liter1 = c | current. liter2 = c)
{
Break;
}
OPERATION iOp;
For (int I = 0; I <6; I ++)
{
IOp = (OPERATION) I;
Nxt = current;
Switch (iOp)
{
Case FILL1:
{
// Fill glass
If (! Visit [a] [nxt. liter2])
{
Q. push (a, nxt. liter2, current. stepID + 1, q. front-1, FILL1 );
Visit [a] [nxt. liter2] = true;
}
Break;
}
Case FILL2:
{
If (! Visit [nxt. liter1] [B])
{
Q. push (nxt. liter1, B, current. stepID + 1, q. front-1, FILL2 );
Visit [nxt. liter1] [B] = true;
}
Break;
}
Case POUR12:
{
Int newA = current. liter1;
Int newB = current. liter2;
If (newA + newB> B)
{
NewA = newA + newB-B;
NewB = B;
}
Else
{
NewB = newA + newB;
NewA = 0;
}
If (! Visit [newA] [newB])
{
Q. push (newA, newB, current. stepID + 1, q. front-1, POUR12 );
Visit [newA] [newB] = true;
}
Break;
}
Case POUR21:
{
Int newA = current. liter1;
Int newB = current. liter2;
If (newA + newB>)
{
NewB = newA + newB-;
NewA =;
}
Else
{
NewA = newA + newB;
NewB = 0;
}
If (! Visit [newA] [newB])
{
Q. push (newA, newB, current. stepID + 1, q. front-1, POUR21 );
Visit [newA] [newB] = true;
}
Break;
}
Case DROP1:
{
If (! Visit [0] [nxt. liter2])
{
Q. push (0, nxt. liter2, current. stepID + 1, q. front-1, DROP1 );
Visit [0] [nxt. liter2] = true;
}
Break;
}
Case DROP2:
{
If (! Visit [nxt. liter1] [0])
{
Q. push (nxt. liter1, 0, current. stepID + 1, q. front-1, DROP2 );
Visit [nxt. liter1] [0] = true;
}
Break;
}
}
}
}
If (q. front = q. rear)
{
Printf ("impossible \ n ");
}
Else
{
Printf ("% d \ n", q. steps [q. front-1]. stepID );
PrintPath (q. front-1 );
}
}
Int main ()
{
Int a, B, c;
While (scanf ("% d", & a, & B, & c )! = EOF)
{
Memset (visit, 0, sizeof (visit ));
BFS (a, B, c );
}
Return 0;
}
Several bugs were made during the compilation, making it impossible to call the SDK for half a day.
Bug1, when newA newB is assigned a value, the order is written incorrectly, ignoring the fact that the two values are dependent.
Bug2, at the end of the traversal, the front-1 is not written. In fact, when the front is finished last time, it is already-1.
Author: hopeztm