```cpp
#include<bits/stdc++.h>
using namespace std;
int a[12];
int two, king;
int ans;
inline void dfs(int step, int pai);
int zha = 0; //炸弹!(可以带)
int san = 0; //三牌!!(也可以带)
int main() {
int t, n;
cin >> t >> n;
while (t--) {
king = two = zha = san = 0;
memset(a, 0, sizeof a);
ans = n;
string c;
for (int i = 0; i < n; ++i) {
cin >> c;
if (c == "0") ++king;
else {
if (c == "2")++two; //2不可加于链子,不同打法
else {
int x = atoi(c.c_str());
if (x ^ 1)x -= 2;
else x = 11;//a>k
++a[x];
}
}
int __TMP_______________HUASE;
cin >> __TMP_______________HUASE;//吃花色
}
dfs(0, n);
cout << ans << endl;
}
return 0;
}
inline void dfs(int step, int pai) {
if (pai == 0) ans = min(step, ans);
else if (ans <= step)return;
else {
if (king == 2) {
king = 0;
dfs(step + 1, pai - 2);
king = 2;
}
for (int i = 0; i < 12; ++i) {
if (a[i] == 4) {
a[i] = 0;
++zha;
dfs(step + 1, pai - 4);
--zha;
a[i] = 4;
}
}
if (two == 4) {
two = 0;
++zha;
dfs(step + 1, pai - 4);
--zha;
two = 4;
}
for (int i = 0; i < 12; ++i)
for (int j = i; j < 12; ++j) {
if (a[j] < 3)break;
if (j - i > 1) {
for (int k = i; k <= j; ++k)--a[k];
dfs(step + 1, pai - (j - i + 1) * 3);
for (int k = i; k <= j; ++k)++a[k];
}
}
for (int i = 0; i < 12; ++i)
for (int j = i; j < 12; ++j) {
if (a[j] < 2)break;
if (j - i > 1) {
for (int k = i; k <= j; ++k)--a[k];
dfs(step + 1, pai - (j - i + 1) * 2);
for (int k = i; k <= j; ++k)++a[k];
}
}
for (int i = 0; i < 12; ++i)
for (int j = i; j < 12; ++j) {
if (!a[j])break;
if (j - i > 1) {
for (int k = i; k <= j; ++k)--a[k];
dfs(step + 1, pai - (j - i + 1));
for (int k = i; k <= j; ++k)++a[k];
}
}
for (int i = 0; i < 12; ++i)if (a[i] >= 3) {
a[i] -= 3;
++san;
dfs(step + 1, pai - 3);
--san;
a[i] += 3;
}
if (two >= 3) {
two -= 3;
++san;
dfs(step + 1, pai - 3);
--san;
two += 3;
}
if (san) { //三代
if (king) {//三代王(不可带一对)
--king;
--san;
dfs(step , pai - 1);
++san;
++king;
}//双王不成对
if (two <= 2) {
int ttt = two;
two = 0;
--san;
dfs(step , pai - ttt);
++san;
two = ttt;
}
for (int i = 0; i < 12; ++i) if (a[i] < 3) {//可带对也可带单
int tt = a[i];
a[i] = 0;
--san;
dfs(step , pai - tt);
++san;
a[i] = tt;
}
}
if (zha) {//炸弹带算一步,出炸弹时已算上
//四代1/2
if (two == 4) {//炸弹带2对2
two = 0;
--zha;
dfs(step , pai - 4);
++zha;
two = 4;
}
if (king == 2) {//炸弹带双王
king = 0;
--zha;
dfs(step , pai - 2);
++zha;
king = 2;
}
if (king && two) { //一个王+一张二
--king;
--two;
--zha;
dfs(step , pai - 2);
++zha;
++two;
++king;
}
for (int i = 0; i < 12; ++i) {//带两个对子
if (a[i] == 2) {
a[i] -= 2;//打出
if (two == 2) {
two -= 2;
--zha;
dfs(step + 1, pai - 4);
++zha;
two += 2;
}
for (int j = 0; j < 12; ++j) {
if (a[j] >= 2) { //打出
a[j] -= 2;
--zha;
dfs(step + 1, pai - 4);
++zha;
a[j] += 2;
}
}
a[i] += 2;
}
}
for (int i = 0; i < 12; ++i)if (a[i]) {
--a[i];
if (king) {
--king;
--zha;
dfs(step + 1, pai - 2);
++zha;
++king;
}
if (two) {
--two;
--zha;
dfs(step + 1, pai - 2);
++two;
++zha;
}
for (int j = 0; j < 12; ++j) if (a[j]) {
--a[j];
dfs(step - 1, pai - 2);
++a[j];
}
++a[i];
}
}
for (int i = 0; i < 12; ++i)if (a[i] >= 2) {
a[i] -= 2;
dfs(step + 1, pai - 1); //对子
a[i] -= 2;
}
if (two) {
two -= 2;
dfs(step + 1, pai - 1);
two += 2;
}
for (int i = 0; i < 12; ++i)if (a[i]) {
--a[i];
dfs(step + 1, pai - 1); //单牌
++a[i];
}
if (king) {
--king;
dfs(step + 1, pai - 1);
++king;
}
if (two) {
--two;
dfs(step + 1, pai - 1);
++two;
}
}
}
```
by tmlrock @ 2023-09-02 22:42:58
4分求调
by tmlrock @ 2023-09-02 22:44:58