1.这一版是不能拆牌的所以花色什么用都没有
2.A和2接在JQK后面存储不需要特判
3.四带的是两张单牌或者两对牌(4张)
4.顺子不带2和双王但是三带一四带二是可以带的(注意双王不算一对牌,只能算单牌)
5.当前步数最多不超过剩余牌数,minn初始化成n,每次统计剩余牌数加上step更新minn
6.有了5.单牌就不需要统计了
7.除顺子外别的牌因为牌数一定,可以算出最少步数,剪个枝
8.按牌数多少安排搜索顺序
9.当前步数大于minn直接return
#include<bits/stdc++.h>
using namespace std;
int ans=0,num[20],minn=17;
void dfs(int step)
{
if(step>=minn) return;
int f=0,sum=0;
for(int i=3;i<=15;i++)
{
if(num[i]>0)
{
f=1;
sum+=num[i];
}
}
if(num[16]>0) sum++;
minn=min(minn,step+sum);
if(f==0) return;
for(int i=3;i<=14;i++)//3顺子
{
int j=i;
for(;j<=14;j++) if(num[j]<3) break;
j--;//j跳出来一定是不合法的,不管是>14还是num[j]<3,下同
for(int jj=j;jj>=i+1;jj--)
{
for(int k=i;k<=jj;k++) num[k]-=3;
dfs(step+1);
for(int k=i;k<=jj;k++) num[k]+=3;
}
}
for(int i=3;i<=14;i++)//2顺子
{
int j=i;
for(;j<=14;j++) if(num[j]<2) break;
j--;
for(int jj=j;jj>=i+2;jj--)
{
for(int k=i;k<=jj;k++) num[k]-=2;
dfs(step+1);
for(int k=i;k<=jj;k++) num[k]+=2;
}
}
for(int i=3;i<=14;i++)//单顺子
{
int j=i;
for(;j<=14;j++) if(num[j]<1) break;
j--;
for(int jj=j;jj>=i+4;jj--)
{
for(int k=i;k<=jj;k++) num[k]--;
dfs(step+1);
for(int k=i;k<=jj;k++) num[k]++;
}
}
if(step+sum/8>minn) return;
for(int i=3;i<=15;i++)//4带2 ,炸弹
{
if(num[i]==4)
{
num[i]-=4;
for(int j=3;j<=16;j++)//带单
{
if(num[j]>0)
for(int k=3;k<=16;k++)
{
if(num[k]>0&&k!=j)//带两单
{
num[j]--;num[k]--;
dfs(step+1);
num[j]++;num[k]++;
}
}
if(num[j]>=2)
{
num[j]-=2;
dfs(step+1);
num[j]+=2;
}
}
for(int j=3;j<=15;j++)//带双
{
if(num[j]>=2)
for(int k=3;k<=15;k++)
if(num[k]>=2&&k!=j)
{
num[j]-=2;num[k]-=2;
dfs(step+1);
num[j]+=2;num[k]+=2;
}
}
dfs(step+1);//炸弹
num[i]+=4;
}
}
if(step+sum/5>minn) return;
for(int i=3;i<=15;i++)//3带2 ,3带1 ,3张牌
{
if(num[i]==3)
{
num[i]-=3;
for(int j=3;j<=15;j++)
{
if(num[j]>=2)
{
num[j]-=2;
dfs(step+1);
num[j]+=2;
}
if(num[j]>0)
{
num[j]--;
dfs(step+1);
num[j]++;
}
}
if(num[16]>0)
{
num[16]--;
dfs(step+1);
num[16]++;
}
dfs(step+1);
num[i]+=3;
}
}
if(step+sum/2>minn) return;
for(int i=3;i<=15;i++)//对子
{
if(num[i]>=2)
{
num[i]-=2;
dfs(step+1);
num[i]+=2;
}
}
}
int main()
{
int t,n;
cin>>t>>n;
while(t--)
{
memset(num,0,sizeof(num));
ans=0; int a1,b1;
minn=n;
for(int i=1;i<=n;i++)
{
cin>>a1>>b1;
if(a1==0) num[16]++;
if(a1==1) num[14]++;
if(a1==2) num[15]++;
if(a1>=3&&a1<=13) num[a1]++;
}
dfs(0);
cout<<ans+minn<<"
";
}
return 0;
}//今天是个好日子啊我的斗地主调出来了