Problem:
Patience

As the proverb says,

"Patience is bitter, but its fruit is sweet."

Writing programs within the limited time may impose
some patience on you, but you enjoy it and win the contest, we hope.

The word "patience" has the meaning of perseverance,
but it has another meaning in card games.
Card games for one player are called "patience" in the UK
and "solitaire" in the US.

Let's play a patience in this problem.

In this card game, you use only twenty cards whose
face values are positive and less than or equal to 5 (Ace's value
is 1 as usual).
Just four cards are available for each face value.

At the beginning, the twenty cards are laid
in five rows by four columns (See Figure 1).
All the cards are dealt face up.

An example of the initial layout is shown in Figure 2.

Figure 1: Initial layout

Figure 2: Example of the initial layout

The purpose of the game is to remove as many cards as possible
by repeatedly removing a pair of neighboring cards
of the same face value.
Let us call such a pair a matching pair.

The phrase "a pair of neighboring cards" means a pair of cards which are
adjacent to each other.
For example, in Figure 1, C6 is adjacent to any of
the following eight cards:

C1,
C2,
C3,
C5,
C7,
C9,
C10 and C11.
In contrast,
C3 is adjacent to only the following three cards:
C2,
C6 and C7.

Every time you remove a pair, you must rearrange the remaining cards
as compact as possible.

To put it concretely, each remaining card Ci
must be examined in turn
in its subscript order to be shifted to the uppermost-leftmost
space.

How to play:

Search a matching pair.

When you find more than one pair, choose one.

In Figure 3, you decided to remove the pair of
C6 and C9.

Remove the pair. (See Figure 4)

Shift the remaining cards to the uppermost-leftmost space
(See Figure 5, 6).

Repeat the above procedure until you cannot remove any pair.

Figure 3: A matching pair found

Figure 4: Remove the matching pair

Figure 5: Shift the remaining cards

Figure 6: Rearranged layout

If you can remove all the twenty cards, you win the game
and your penalty is 0.
If you leave some cards,
you lose the game and
your penalty is the number of the remaining cards.

Whenever you find multiple matching pairs,
you must choose one pair out of them
as in the step 2 of the above procedure.
The result of the game depends on these choices.

Your job is to write a program which answers the minimal penalty
for each initial layout.

Input

The input consists of multiple card layouts.
The input is given in the following format.

N
Layout0
Layout1
...
LayoutN-1

N is the number of card layouts.
Each card layout gives the initial state of a game.
A card layout is given in the following format.

C0 C1 C2 C3
C4 C5 C6 C7
C8 C9 C10 C11
C12 C13 C14 C15
C16 C17 C18 C19

Ci (0 <= i <= 19) is an integer
from 1 to 5 which represents the face value of the card.

Output

For every initial card layout, the minimal penalty should be output,
each in a separate line.

Sample Input

4
1 4 5 2
3 1 4 3
5 4 2 2
4 5 2 3
1 1 3 5
5 1 5 1
4 5 3 2
3 2 1 4
1 4 5 3
2 3 4 2
1 2 1 2
5 4 5 4
2 1 2 1
3 5 3 4
3 3 5 4
4 2 3 1
2 5 3 1
3 5 4 2
1 5 4 1
4 5 3 2

Output for the Sample Input

0
4
12
0

Solution in C# (judge verdict: Accepted)

using System.Linq;
using static System.Math;
using System.Collections.Generic;
using System;


public class hello
{
    public static int[] dx, dy;

    public static void Main()
    {
        dx = new int[] { 0, 1, 1, 1,  };
        dy = new int[] { 1, 1, 0, -1 };
        var n = int.Parse(Console.ReadLine().Trim());
        var p = 0;
        while (p < n)
        {
            var s = "";
            for (int i = 0; i < 5; i++)
            {
                string[] line = Console.ReadLine().Trim().Split(' ');
                for (int j = 0; j < 4; j++) s += line[j];
            }
            getAns(s);

            p++;
        }
    }
    static void getAns(string s)
    {
        var hs = new HashSet<string>();
        var q = new Queue<string>();
        var ans = int.MaxValue;
        q.Enqueue(s);
        while (q.Count() > 0)
        {
            var w = q.Dequeue();
            ans = Min(ans, w.Length);
            var a = stringToarray(w);
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (a[i, j] == '\0') goto exit;
                    for (int k = 0; k < 4; k++)
                    {
                        var x = i + dx[k];
                        var y = j + dy[k];
                        if (x >= 0 && x < 5 && y >= 0 && y < 4 && a[i, j] == a[x, y])
                        {
                            var t = a[i, j];
                            a[i, j] = '0';
                            a[x, y] = '0';
                            var ts = arrayTostring(a, w.Length );
                            if (hs.Add(ts))     q.Enqueue(ts);
                            a[i, j] = t;
                            a[x, y] = t;
                        }
                    }
                }
            }
            exit:;
        }
        Console.WriteLine(ans);
    }
    static string arrayTostring(char[,] a, int n)
    {
        var c = 0;
        var ans = "";
        for (int i = 0; i < 5; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                if (a[i, j] != '0') ans += a[i, j];
                c++;
                if (c == n) return ans;
            }
        }
        return ans;
    }
    static char[,] stringToarray(string s)
    {
        var a = new char[5, 4];
        if (s.Length == 0) return a;
        var p = 0;
        var sL = s.Length;
        while (true)
        {
            for (int i = 0; i < 5; i++)
                for (int j = 0; j < 4; j++)
                {
                    if (s[p] != '0') a[i, j] = s[p];
                    p++;
                    if (p >= sL) return a;
                }
        }
    }
}