# Card Game

Given series of card and a number K, if there are three consecutive cards a, b and c conforms that a + K = b and b + K = c, we can drop the three cards off. Then after serveral round of dropping, what's the least possible number of cards remains (which can not be drop any more).

This is a dynamic programming problem. Let is the minimum number of cards remains after dropping cards in str[i..j] (i, j inclusive), then we can write the following iterate formular:

What's more, when cards[i] + K = cards[k] and cards[k] + K = cards[j] as well as we have .

We can compress the space cost of DP matrix, but by doing so, the iteration order to calculate the values is very important and should be handled with attention.

import java.io.*;
import java.util.*;

public class CardGame {
private static int solve(int[] array, int N, int K) {
int[][] DP = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = i; j < N; j++) {
DP[i][j] = j - i + 1;
}
}
for (int r = 2; r < N; r++) {
for (int l = r - 2; l >= 0; l--) {
int min = DP[l][r];
for (int m = l; m < r; m++) {
min = Math.min(min, DP[l][m] + DP[m + 1][r]);
}
for (int m = l + 1; m < r; m++) {
if (array[l] + K != array[m] || array[m] + K != array[r]) continue;
int lmin = DP[l + 1][m - 1];
int rmin = DP[m + 1][r - 1];
if (lmin == 0 && rmin == 0) {
min = 0;
}
}
DP[l][r] = min;
}
}
return DP[N - 1];
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int T = in.nextInt();
for (int t = 0; t < T; t++) {
int N = in.nextInt(), K = in.nextInt();
int[] array = new int[N];
for (int i = 0; i < N; i++) {
array[i] = in.nextInt();
}
System.out.printf("Case #%d: %d\n", t + 1, solve(array, N, K));
}
}
}