暴力不解释,数据随机生成,我们可以贪心的按打出牌的数量从多到少出,那么这样就能够使最优化剪枝起到很重要的作用,怎样简化代码呢?我从题解中发现了一种将单顺子,双顺子和三顺子合成一种的方法,具体实现看代码,另外我们不要考虑一种牌一下出1--4张的情况,因为如果我们把其他情况考虑完后,剩下多少种牌就要出几次,这样的话代码量就会减少一部分。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int cnt[17],T,n,ans=100;
int flag[15];
const int sz[4]={0,5,3,2};
void dfs(int x)
{
if (x>ans) return;
for (int i=3;i>=1;i--)
{
int l=0;
if (i==1)
{
int b=5;
}
for (int j=3;j<=14;j++)
{
if (cnt[j]<i) l=0;else l++;
if (l>=sz[i])
{
for (int k=j;k>j-l;k--) cnt[k]-=i;
dfs(x+1);
for (int k=j;k>j-l;k--) cnt[k]+=i;
}
}
}
for (int i=2;i<=14;i++)
{
if (cnt[i]>=4)
{
cnt[i]-=4;
for (int j=2;j<=14;j++)
{
if (j==i||cnt[j]<2) continue;
cnt[j]-=2;
for (int k=2;k<=14;k++)
{
if (k==j||cnt[k]<2) continue;
cnt[k]-=2;
dfs(x+1);
cnt[k]+=2;
}
cnt[j]+=2;
}
for (int j=2;j<=15;j++)
{
if (j==i||cnt[j]<1) continue;
cnt[j]-=1;
for (int k=2;k<=15;k++)
{
if (k==j||cnt[k]<1) continue;
cnt[k]-=1;
dfs(x+1);
cnt[k]+=1;
}
cnt[j]+=1;
}
cnt[i]+=4;
}
}
for (int i=2;i<=14;i++)
{
if (cnt[i]>=3)
{
cnt[i]-=3;
for (int j=2;j<=14;j++)
{
if (i==j||cnt[j]<2) continue;
cnt[j]-=2;
dfs(x+1);
cnt[j]+=2;
}
for (int j=2;j<=15;j++)
{
if (i==j||cnt[j]<1) continue;
cnt[j]-=1;
dfs(x+1);
cnt[j]+=1;
}
cnt[i]+=3;
}
}
for (int i=2;i<=15;i++)
if (cnt[i]>0) x++;
ans=min(ans,x);
}
int main()
{
scanf("%d%d",&T,&n);
while (T--)
{
memset(cnt,0,sizeof cnt);
ans=100;
for (int i=1;i<=n;i++)
{
int s;
scanf("%d",&s);
if (s==0) cnt[15]++;else cnt[s]++;
scanf("%d",&s);
}
cnt[14]=cnt[1];
dfs(0);
printf("%d\n",ans);
}
return 0;
}