code+注释
#include<bits/stdc++.h>
using namespace std;
int ans=0xffffff;
int sum[17];//当前第i种排出现了几次
int T,n;
void dfs(int x){
if(x>=ans) return;//下面是顺子
int s1=0;//单顺子
for(int i=3;i<=14;i++){
if(sum[i]==0) s1=0;//顺子结束
else{
s1++;
if(s1>=5){//已经构成顺子,出牌
for(int j=i;j>=i-s1+1;j--) sum[j]--;//出顺子
dfs(x+1);
for(int j=i;j>=i-s1+1;j--) sum[j]++;//撤回
}
}
}
int s2=0;//双顺子
for(int i=3;i<=14;i++){
if(sum[i]<2) s2=0;//顺子结束
else{
s2++;
if(s2>=3){//已经构成顺子,出牌
for(int j=i;j>=i-s1+1;j--) sum[j]-=2;//出顺子
dfs(x+1);
for(int j=i;j>=i-s1+1;j--) sum[j]+=2;//撤回
}
}
}
int s3=0;//三顺子
for(int i=3;i<=14;i++){
if(sum[i]<3) s3=0;//顺子结束
else{
s3++;
if(s3>=2){//已经构成顺子,出牌
for(int j=i;j>=i-s1+1;j--) sum[j]-=3;//出顺子
dfs(x+1);
for(int j=i;j>=i-s1+1;j--) sum[j]+=3;//撤回
}
}
}
for(int i=2;i<=14;i++){//带牌
if(sum[i]<=2) continue;//不能带牌(三张以上才能)
else if(sum[i]==3){//当前有三张牌,可构成三带一、三带二。
sum[i]-=3;//打掉三张
for(int j=2;j<=15;j++){//三带一
if(sum[j]<=0 || j==i) continue;//若没有牌或带的是自己这种牌(没了),那不能打
sum[j]--;//三带一
dfs(x+1);
sum[j]++;//回溯
}
for(int j=2;j<=14;j++){//三带二,不选大王小王(15)
if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
sum[j]-=2;//三带二
dfs(x+1);
sum[j]+=2;//回溯
}
sum[i]+=3;//回溯,选别的牌。
}
else{//有四张以上的牌
sum[i]-=3;//1.打掉三张
for(int j=2;j<=15;j++){//三带一
if(sum[j]<=0 || j==i) continue;//若没有牌或带的是自己这种牌(没了),那不能打
sum[j]--;//三带一
dfs(x+1);
sum[j]++;//回溯
}
for(int j=2;j<=14;j++){//三带二,不选大王小王(15)
if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
sum[j]-=2;//三带二
dfs(x+1);
sum[j]+=2;//回溯
}
sum[i]+=3;//回溯,选另外的方案。
sum[i]-=4;//2.打掉四张
for(int k=2;k<=15;k++){//四带二
if(sum[k]<=0 || k==i) continue;//若没有一张牌或带的是自己这种牌,不能打
sum[k]--;//出第一张牌
for(int j=2;j<=15;j++){//四带二
if(sum[j]<=0 || j==k) continue;//若没有牌或带的是自己这种牌(没了),那不能打
sum[j]--;//四带二
dfs(x+1);
sum[j]++;//回溯
}
sum[k]++;//回溯
}
for(int k=2;k<=14;k++){//四带四,不选大王小王(15)
if(sum[k]<=1 || k==i) continue;//同上
sum[k]-=2;//同上
for(int j=2;j<=14;j++){//四带四
if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
sum[j]-=2;//四带二
dfs(x+1);
sum[j]+=2;//回溯
}
sum[k]+=2;//同上
}
sum[i]+=4;//回溯,选另外的方案。
}
}
for(int i=2;i<=15;i++) if(sum[i]) x++;//出光
ans=min(ans,x);//更新答案
}
int main(){
cin>>T>>n;//数据组数和张数
while(T--){
ans=0xffffff;//初始的ans
int a,b;//题目中ai和bi
memset(sum,0,sizeof(sum));//每回都将次数清0
for(int i=1;i<=n;i++){
cin>>a>>b;//第i种花色和牌
if(a==0) sum[15]++;//大王和小王
else if(a==1) sum[14]++;//根据牌值排序
else sum[a]++;//根据牌值排序
}
dfs(0);//搜索
cout<<ans<<endl;//输出结果
}
return 0;
}