Official Analysis (C++)

Solution

Explanation

In line with the spirit of range DP, let's define dp[i][j]dp[i][j] as the minimum number of swipes it takes to clear all the gems between indices ii and jj inclusive. If i>ji > j then there's no gems in the range and the array will return 00.

There's two situations we can transition from.

The first is comparatively simpler, and it's where we erase either the first or first two elements from the array (if they're equal). In this case, the value we get is dp[i+1][j]+1dp[i+1][j]+1 or dp[i+2][j]+1dp[i+2][j]+1.

The second case is a bit nastier, and it may seem a bit unintuitive at first:

If i+2kji + 2 \le k \le j and the gems at positions ii and kk are the same color, then we can update with the following candidate value:

dp[i+1][k1]+dp[k+1][j]dp[i+1][k-1]+dp[k+1][j]

You may wonder why there's no extra swipe involved in this transition. After all, where did we clear gems ii and kk?

The answer is that we can clear them along with the last swipe that erased what was left in dp[i+1][k1]dp[i+1][k-1]. Since the last swipe that cleared these gems was a palindrome, we can take on ii and kk to the start and end without any problems.

Implementation

Time Complexity: O(N3)\mathcal{O}(N^3)

Java

import java.io.*;
import java.util.Arrays;
public class Zuma {
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
int gemNum = Integer.parseInt(read.readLine());
int[] gems = Arrays.stream(read.readLine().split(" "))
.mapToInt(Integer::parseInt)
.toArray();

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!