版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83782942
传送门
解析:
其实不考虑点数大小的话只有张数对我们是有用的。所以可以预处理出有 张单牌, 张对子, 张三条, 个炸弹, 个王的情况下打完散牌要的最少次数,顺子通过贪心搜索一下就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void ckmin(int &x,cs int &val){
if(x>val)x=val;
}
int f[26][14][12][8][3];
inline void init(){
memset(f,0x3f,sizeof f);
f[0][0][0][0][0]=0;
for(int re z=0;z<7;++z)
for(int re k=0;k<10;++k)
for(int re i=0;i<24;++i)
for(int re j=0;j<13;++j)
for(int re l=0;l<3;++l){
int &x=f[i][j][k][z][l];
if(i>0)ckmin(x,f[i-1][j][k][z][l]+1);
if(j>0)ckmin(x,f[i][j-1][k][z][l]+1);
if(k>0)ckmin(x,f[i][j][k-1][z][l]+1);
if(z>0)ckmin(x,f[i][j][k][z-1][l]+1);
if(l>0)ckmin(x,f[i][j][k][z][l-1]+1);
if(l>1)ckmin(x,f[i][j][k][z][l-2]+1);
if(k>0&&i>0)ckmin(x,f[i-1][j][k-1][z][l]+1);
if(k>0&&l>0)ckmin(x,f[i][j][k-1][z][l-1]+1);
if(k>0&&j>0)ckmin(x,f[i][j-1][k-1][z][l]+1);
if(z>0&&i>1)ckmin(x,f[i-2][j][k][z-1][l]+1);
if(z>0&&i>0&&l>0)ckmin(x,f[i-1][j][k][z-1][l-1]+1);
if(z>0&&l>1)ckmin(x,f[i][j][k][z-1][l-2]+1);
if(z>0&&j>0)ckmin(x,f[i][j-1][k][z-1][l]+1);
if(z>0&&j>1)ckmin(x,f[i][j-2][k][z-1][l]+1);
if(z>1)ckmin(x,f[i][j][k][z-2][l]+1);
if(z>0)ckmin(x,f[i+1][j][k+1][z-1][l]);
if(z>0)ckmin(x,f[i][j+2][k][z-1][l]);
if(k>0)ckmin(x,f[i+1][j+1][k-1][z][l]);
}
}
int ans;
int a[20];
int cnt[6];int T,n;
void dfs(int x){
if(x>=ans)return ;
memset(cnt,0,sizeof cnt);
for(int re i=1;i<=13;++i)++cnt[a[i]];cnt[5]=a[14];
ans=min(ans,x+f[cnt[1]][cnt[2]][cnt[3]][cnt[4]][cnt[5]]);
for(int re k=1;k<=3;++k){
for(int re i=1;i<=12;++i){
bool flag=true;
int cnt=(k==1)?5:(k==2?3:2);
while(flag&&i+cnt-1<=12){
for(int re j=1;j<=cnt;++j)if(a[i+j-1]<k){
flag=false;
break;
}
if(!flag)break;
for(int re j=1;j<=cnt;++j)a[i+j-1]-=k;
dfs(x+1);
for(int re j=1;j<=cnt;++j)a[i+j-1]+=k;
++cnt;
}
}
}
}
signed main(){
init();
T=getint();
n=getint();
while(T--){
ans=n;
memset(a,0,sizeof a);
for(int re i=1;i<=n;++i){
int num=getint();getint();
if(num==0){
++a[14];
continue;
}
if(num>2)++a[num-2];
else ++a[num+11];
}
dfs(0);
printf("%d\n",ans);
}
return 0;
}