简单,暴力模拟
#include<cstdio>
#include<cstring>
using namespace std;
int a[18],f[18][18][18][18];
int ans;
int min(int x,int y){return x<y ? x:y;}
int biao(int a,int b,int c,int d)
{
int s=a+b+c+d;
if (a>0) s=min(s,f[a-1][b][c][d]+1);
if (b>0) s=min(s,f[a][b-1][c][d]+1);
if (c>0) s=min(s,f[a][b][c-1][d]+1);
if (d>0) s=min(s,f[a][b][c][d-1]+1);
if (a>0 && c>1) s=min(s,f[a-1][b][c-2][d]+1);
if (a>0 && d>1) s=min(s,f[a-1][b][c][d-2]+1);
if (b>0 && c>0) s=min(s,f[a][b-1][c-1][d]+1);
if (b>0 && d>0) s=min(s,f[a][b-1][c][d-1]+1);
return s;
}
void dfs(int s)
{
int i,j;
int b=0,c=0,d=0,e=0;
for (i=3;i<=16;i++)
{
if (a[i]==4) b++;
else if (a[i]==3) c++;
else if (a[i]==2) d++;
else if (a[i]==1) e++;
}
ans=min(ans,f[b][c][d][e]+s);
for (i=3;i<=16;i++)
{
j=0;
while (i+j<=14&&a[i+j]>=1)//单顺子
{
if (j>=4)
{
for (int k=i;k<=i+j;k++) a[k]--;
dfs(s+1);
for (int k=i;k<=i+j;k++) a[k]++;
}
j++;
}
j=0;
while (i+j<=14&&a[i+j]>=2)//双顺子
{
if (j>=2)
{
for (int k=i;k<=i+j;k++) a[k]-=2;
dfs(s+1);
for (int k=i;k<=i+j;k++) a[k]+=2;
}
j++;
}
j=0;
while (i+j<=14&&a[i+j]>=3)//三顺子
{
if (j>=2)
{
for (int k=i;k<=i+j;k++) a[k]-=3;
dfs(s+1);
for (int k=i;k<=i+j;k++) a[k]+=3;
}
j++;
}
}
}
int main()
{
freopen("landlords.in","r",stdin);
freopen("landlords.out","w",stdout);
int t,n,i,j,k,l;
scanf("%d%d",&t,&n);
for (i=0;i<=17;i++)
for (j=0;j<=17;j++)
for (k=0;k<=17;k++)
for (l=0;l<=17;l++)
f[i][j][k][l]=biao(i,j,k,l);
while (t-->0)
{
memset(a,0,sizeof(a));
for (i=1;i<=n;i++)
{
scanf("%d%d",&j,&k);
if (j>2) a[j]++;
else if (j>0) a[j+13]++;
else a[16]++;
}
ans=1e9;
dfs(0);
printf("%d
",ans);
}
return 0;
}