GRDJUMP - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: iceknight1093
Tester: raysh07
Editorialist: iceknight1093

DIFFICULTY:

Cakewalk

PREREQUISITES:

None

PROBLEM:

You start at (0, 0) and want to reach (A, B).
You can:

  • Move upto two steps right, for a cost of P.
  • Move upto two steps up, for a cost of Q.
  • Move one step right and one up, for a cost of R.

Find the minimum cost to reach (A, B).

EXPLANATION:

The up/right movements are basically independent of each other - only the diagonal move combines them.

So, let’s try and fix the number of diagonal moves we make.
Suppose we make d diagonal moves. This has a cost of d\cdot R, and will leave us at (d, d).

After that, only up/right moves can be made, and those are independent so we treat them separately.

  • The x-coordinate is currently d but needs to become A.
    • If d \gt A this is impossible since we can only increase it.
    • So, assume d \le A, and we need to cover a distance of A-d with the rightward moves.
    • It’s optimal to move two steps as many times as we can; with maybe only the last move being one step.
      So, the number of moves equals \text{ceiling}\left(\frac{A-d}{2}\right), with the cost being this quantity multiplied by P.
  • The y-coordinate is currently d but needs to become B.
    • Again, if d \gt B this is impossible.
    • If d \le B then the same reasoning tells us that the number of moves needed equals \text{ceiling}\left(\frac{B-d}{2}\right), so multiply this by Q to get the cost of this part.

Thus, with d fixed, the remaining cost can be computed in constant time.

Since A, B \le 100 and we only need to try d \in [0, \min(A, B)], this \mathcal{O}(\min(A, B)) algorithm is perfectly fast - we can simply try all valid d, compute the cost for each, and take the best answer.

TIME COMPLEXITY:

\mathcal{O}(\min(A, B)) per testcase.

CODE:

Editorialist's code (PyPy3)
for _ in range(int(input())):
    a, b, x, y, z = map(int, input().split())

    ans = 10**9
    for d in range(0, min(a, b)+1):
        ans = min(ans, d*z + x*((a-d+1)//2) + y*((b-d+1)//2))
    print(ans)