Problem:
Score : 600 points

Problem Statement

We have 3N cards arranged in a row from left to right, where each card has an integer between 1 and N (inclusive) written on it. The integer written on the i-th card from the left is A_i.

You will do the following operation N-1 times:

Rearrange the five leftmost cards in any order you like, then remove the three leftmost cards. If the integers written on those three cards are all equal, you gain 1 point.

After these N-1 operations, if the integers written on the remaining three cards are all equal, you will gain 1 additional point.

Find the maximum number of points you can gain.

Constraints

1 \leq N \leq 2000

1 \leq A_i \leq N

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 \cdots A_{3N}

Output

Print the maximum number of points you can gain.

Sample Input 1

2
1 2 1 2 2 1

Sample Output 1

2

Let us rearrange the five leftmost cards so that the integers written on the six cards will be 2\ 2\ 2\ 1\ 1\ 1 from left to right.

Then, remove the three leftmost cards, all of which have the same integer 2, gaining 1 point.

Now, the integers written on the remaining cards are 1\ 1\ 1.

Since these three cards have the same integer 1, we gain 1 more point.

In this way, we can gain 2 points - which is the maximum possible.

Sample Input 2

3
1 1 2 2 3 3 3 2 1

Sample Output 2

1

Sample Input 3

3
1 1 2 2 2 3 3 3 1

Sample Output 3

3

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#define maxn 2333
using namespace std;
int a[maxn * 3];
int dp[maxn][maxn];
int DP[maxn][maxn];
int main() {
//	freopen("F.in", "r", stdin);
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= 3 * n; ++i) {
		scanf("%d", a + i);
	}
	if(n == 1) {
		printf("%d\n", a[1] == a[2] && a[2] == a[3]);
	} else {
		if(a[1] > a[2]) swap(a[1], a[2]);
		for(int i = 1; i < n; ++i) {
			int I = 3 * i;
			if(a[I] > a[I + 1]) swap(a[I], a[I + 1]);
			if(a[I + 1] > a[I + 2]) swap(a[I + 1], a[I + 2]);
			if(a[I] > a[I + 1]) swap(a[I], a[I + 1]);
		}
		int Max = 0;
		memset(dp, 0x80, sizeof dp);
		memset(DP, 0x80, sizeof DP);
		dp[a[1]][a[2]] = dp[a[2]][a[1]] = 0; // i <= j
		queue<int> qi, qj;
		int tot = 0;
		for(int i = 1; i < n; ++i) {
			int id = i * 3, x, y, z;
			x = a[id], y = a[id + 1], z = a[id + 2];
			if(x == y && y == z) {
				++tot;
				continue;
			}
			DP[x][y] = DP[y][z] = DP[x][z] = Max; // draw 1 card
			DP[y][x] = DP[z][y] = DP[z][x] = Max;
			for(int i = 1; i <= n; ++i) { // draw 2 card
				DP[x][x] = max(DP[x][x], dp[i][x] + (i == y && y == z));
				DP[i][y] = DP[y][i] = max(DP[i][y], dp[i][x] + (x == z));
				DP[i][z] = DP[z][i] = max(DP[i][z], dp[i][x] + (x == y));
			}
			for(int i = 1; i <= n; ++i) {
				DP[y][y] = max(DP[y][y], dp[i][y] + (i == x && x == z));
				DP[i][x] = DP[x][i] = max(DP[i][x], dp[i][y] + (y == z));
				DP[i][z] = DP[z][i] = max(DP[i][z], dp[i][y] + (y == x));
			}
			for(int i = 1; i <= n; ++i) {
				DP[z][z] = max(DP[z][z], dp[i][z] + (i == x && x == y));
				DP[i][x] = DP[x][i] = max(DP[i][x], dp[i][z] + (z == y));
				DP[i][y] = DP[y][i] = max(DP[i][y], dp[i][z] + (z == x));
			}
			for(int i = 1; i <= n; ++i) {
				Max = max(Max, DP[i][x]);
				Max = max(Max, DP[i][y]);
				Max = max(Max, DP[i][z]);
				dp[i][x] = dp[x][i] = DP[i][x];
				dp[i][y] = dp[y][i] = DP[i][y];
				dp[i][z] = dp[z][i] = DP[i][z];
			}
			for(int i = 1; i <= n; ++i) DP[i][x] = DP[x][i] = DP[i][y] = DP[y][i] = DP[i][z] = DP[z][i] = 0x80808080;
		}
		int Ans = 0;
		for(int i = 1; i <= n; ++i) {
			for(int j = 1; j <= n; ++j) {
				Ans = max(Ans, dp[i][j] + (i == j && j == a[3 * n]));
			}
		}
		Ans += tot;
		printf("%d\n", Ans);
	}
	return 0;
}