先考虑没有顺子的情况,设 $dp_{a,b,c,d}$ 表示 $a$ 张单牌,$b$ 个对子,$c$ 个三张牌,$d$ 个炸弹,在不用顺子情况下出完的最少步数。
这个 $dp$ 很简单,注意的是会有拆牌的情况,将 $4$ 个 $A$ 拆成 $3$ 个 $A$ 和 $1$ 个 $A$,对应 $d \gets d - 1, a \gets a + 1, c \gets c + 1$。
然后考虑对子,我们直接暴搜,由于对多 $23$ 张牌,所以复杂度可过。
#include <bits/stdc++.h>
using namespace std;
int dp[60][30][20][20];
void upd(int &a, int b) {a = min(a, b);}
void Init() {
memset(dp, 0x3f, sizeof dp);
dp[0][0][0][0] = 0;
for (int ____ = 0; ____ <= 13; ____ ++ ) for (int ___ = 0; ___ <= 13; ___ ++ ) for (int __ = 0; __ <= 26; __ ++ ) for (int _ = 0; _ <= 54; _ ++ ) {
if (_) upd(dp[_][__][___][____], dp[_ - 1][__][___][____] + 1);
if (__) upd(dp[_][__][___][____], dp[_][__ - 1][___][____] + 1);
if (___) upd(dp[_][__][___][____], dp[_][__][___ - 1][____] + 1);
if (____) upd(dp[_][__][___][____], dp[_][__][___][____ - 1] + 1);
if (_ && ___) upd(dp[_][__][___][____], dp[_ - 1][__][___ - 1][____] + 1);
if (__ && ___) upd(dp[_][__][___][____], dp[_][__ - 1][___ - 1][____] + 1);
if (_ > 1 && ____) upd(dp[_][__][___][____], dp[_ - 2][__][___][____ - 1] + 1);
if (__ > 1 && ____) upd(dp[_][__][___][____], dp[_][__ - 2][___][____ - 1] + 1);
if (____) upd(dp[_][__][___][____], dp[_ + 1][__][___ + 1][____ - 1]);
if (____) upd(dp[_][__][___][____], dp[_][__ + 2][___][____ - 1]);
if (___) upd(dp[_][__][___][____], dp[_ + 1][__ + 1][___ - 1][____]);
if (__) upd(dp[_][__][___][____], dp[_ + 2][__ - 1][___][____]);
}
}
int n, a[20], joker, ans;
void dfs(int step) {
vector<int> h(5);
for (int i = 1; i <= 13; i ++ ) h[a[i]] ++ ;
ans = min(ans, step + dp[h[1] + joker][h[2]][h[3]][h[4]]);
if (joker == 2) ans = min(ans, step + dp[h[1]][h[2]][h[3]][h[4]] + 1);
for (int i = 3; i <= 10; i ++ ) {
for (int j = 0; ; j ++ ) {
if (i + j == 14) {
if (a[1] && j >= 4) {
for (int k = i; k < i + j; k ++ ) a[k] -- ;
a[1] -- ;
dfs(step + 1);
for (int k = i; k < i + j; k ++ ) a[k] ++ ;
a[1] ++ ;
}
break;
}
if (!a[i + j]) break;
else {
if (j >= 4) {
for (int k = i; k <= i + j; k ++ ) a[k] -- ;
dfs(step + 1);
for (int k = i; k <= i + j; k ++ ) a[k] ++ ;
}
}
}
}
for (int i = 3; i <= 12; i ++ ) {
for (int j = 0; ; j ++ ) {
if (i + j == 14) {
if (a[1] >= 2 && j >= 2) {
for (int k = i; k < i + j; k ++ ) a[k] -= 2;
a[1] -= 2;
dfs(step + 1);
for (int k = i; k < i + j; k ++ ) a[k] += 2;
a[1] += 2;
}
break;
}
if (a[i + j] < 2) break;
else {
if (j >= 2) {
for (int k = i; k <= i + j; k ++ ) a[k] -= 2;
dfs(step + 1);
for (int k = i; k <= i + j; k ++ ) a[k] += 2;
}
}
}
}
for (int i = 3; i <= 12; i ++ ) {
for (int j = 0; ; j ++ ) {
if (i + j == 14) {
if (a[1] >= 3 && j >= 1) {
for (int k = i; k < i + j; k ++ ) a[k] -= 3;
a[1] -= 3;
dfs(step + 1);
for (int k = i; k < i + j; k ++ ) a[k] += 3;
a[1] += 3;
}
break;
}
if (a[i + j] < 3) break;
else {
if (j >= 1) {
for (int k = i; k <= i + j; k ++ ) a[k] -= 3;
dfs(step + 1);
for (int k = i; k <= i + j; k ++ ) a[k] += 3;
}
}
}
}
}
void solve() {
joker = 0;
memset(a, 0, sizeof a);
for (int i = 0; i < n; i ++ ) {
int x, y;
scanf("%d%d", &x, &y);
if (x == 0) {
joker ++ ;
} else {
a[x] ++ ;
}
}
ans = 0721;
dfs(0);
printf("%d\n", ans);
}
int main() {
Init();
int T;
scanf("%d%d", &T, &n);
while (T -- ) solve();
return 0;
}