Video Solution

By David Zhou

Video Solution Code (DFS + BFS Explanation; Only BFS Code)

Official Analysis (Java)

Solution 1 (DFS)

Explanation

We can perform a DFS starting from the base state of (0,0)(0, 0), where both pails have 00 units of milk.

Note that we need to use a 3D grid to correctly track visited states, though. This is because the DFS may visit the same (i,j)(i, j) state earlier in its processing but through a greater number of operations. To properly track visited cells, we need to make sure the visited grid has a record for how many operations it took to reach each state every time.

Simulating all six operations every time is enough to pass the constraints.

Implementation

Time Complexity: O(XYK)\mathcal O(XYK)

MAX_OPS = 100
x, y, k, m = map(int, open("pails.in", "r").read().split())
sol = float("inf")
vis = [
[[False for a in range(MAX_OPS + 1)] for b in range(MAX_OPS + 1)]
for c in range(MAX_OPS + 1)
]

Solution 2 (BFS)

Explanation

We can directly simulate all operations using BFS.

In this problem, we care about states (i,j)(i, j) where pail XX has ii and pail YY has jj units of milk. We can perform a BFS starting from base state (0,0)(0, 0) to compute dist[i][j]\texttt{dist}[i][j], the minimum number of steps to reach each state. Afterwards, compute the answer by iterating over all states where dist[i][j]K\texttt{dist}[i][j] \le K and finding the minimum i+jM|i+j-M|.

For every transition in the BFS, we simulate all possible actions.

  1. Fill either pail completely to the top: set ii to XX or jj to YY.
  2. Empty either pail: set ii or jj to 00.
  3. Pour the contents of one pail into another without overflowing or running out of milk.

To perform operation 3, we can find the amount poured to be min(i,Yj)\min(i, Y-j) or min(j,Xi)\min(j, X-i) depending on which pail you pour from. Then add/subtract this quantity to each pail appropriately.

Now iterate over all states (i,j)(i, j) where dist[i][j]K\texttt{dist}[i][j] \le K and compute the minimum i+jM|i+j-M|.

Implementation

Time Complexity: O(XY)\mathcal O(XY)

from collections import deque
import sys
sys.stdin, sys.stdout = open("pails.in", "r"), open("pails.out", "w")
input = sys.stdin.readline
def generate_permutations(p1: int, p2: int):
# generates results of all possible pours
da = min(p2, x - p1) # amount poured when pouring p2 into p1

Solution 3 (DP)

Explanation

The states in this problem are a combination of the milk amounts in each pail and the number of operations to reach such amounts.

Let f[i][j][l]\text{f}[i][j][l] represent if it is possible to reach ii and jj pail amounts in ll operations. Our base case is f[0][0][0]\text{f}[0][0][0] as true, since there is no milk initially. Now, iterate through all ll such that 0l<K0\leq l<K, and all possible ii and jj. For any true state f[i][j][l]\text{f}[i][j][l], mark f[i][j][l+1]\text{f}[i'][j'][l+1] as true for all (i,j)(i', j')'s that can result from a single operation based on (i,j)(i, j). The possible operations are explained in the previous solutions.

The answer is the minimum of i+jm|i+j-m| for all true f[i][j][l]\texttt{f}[i][j][l].

Implementation

Time Complexity: O(XYK)\mathcal O(XYK)

#include <climits>
#include <fstream>
#include <vector>
using namespace std;
int main() {
ifstream fin("pails.in");
int x, y, k, m;
fin >> x >> y >> k >> m;

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!