%%%Luan
题面就不说了,和斗地主一样,给一组牌,求最少打几次。
注意一点,数据随机,这样我们瞎搞一搞就可以过,虽然直接贪心可以证明是错的。
枚举方法,每次搜索按照(三顺子>二顺子>普通顺子)枚举一个进入下一层搜索。
在每层搜索中我们都要枚举打其他牌的方法,用贪心的结果+顺子数来更新答案。
具体方法是(想象你手里有这么多牌你该怎么打),枚举四代二,四代一,三代二,三代一,对和单。
注意我要带的必须是恰好两个或一个,不然会被随机数据hack。。
Code
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int di[20],cnt[20],ans,n,t,a,b; inline int counting(){ int jians=0; for(int i=1;i<=14;++i)di[i]=cnt[i]; for(int i=1;i<=13;++i) if(di[i]>=4) for(int j=1;j<=14;++j) if(i!=j&&di[j]==2&&di[i]>=4) for(int k=j+1;k<=14;++k) if(k!=i&&di[k]==2){di[i]-=4;di[j]-=2;di[k]-=2;jians++;break;} for(int i=1;i<=13;++i) if(di[i]>=4) for(int j=1;j<=14;++j) if(i!=j&&di[j]==1&&di[i]>=4) for(int k=j+1;k<=14;++k) if(k!=i&&di[k]==1){di[i]-=4;di[j]--;di[k]--;jians++;break;} for(int i=1;i<=13;++i) if(di[i]>=4) for(int j=1;j<=14;++j) if(i!=j&&di[j]==2){di[j]-=2;di[i]-=4;jians++;break;} for(int i=1;i<=13;++i)while(di[i]>=4)jians++,di[i]-=4; for(int i=1;i<=13;++i) if(di[i]>=3) for(int j=1;j<=14;++j) if(i!=j&&di[j]==2){if(di[i]<3)break;di[i]-=3;di[j]-=2;jians++;} for(int i=1;i<=13;++i) if(di[i]>=3) for(int j=1;j<=14;++j) if(i!=j&&di[j]==1){if(di[i]<3)break;di[j]--;di[i]-=3;jians++;} for(int i=1;i<=13;++i)while(di[i]>=3)jians++,di[i]-=3; for(int i=1;i<=14;++i)while(di[i]>=2)jians++,di[i]-=2; for(int i=1;i<=14;++i)while(di[i])jians++,di[i]--; return jians; } void dfs(int deep){ if(deep>=ans)return; for(int i=1;i<=14;++i){ if(cnt[i])break; if(i==14){ ans=deep;return; } } // for(int i=1;i<=14;++i)cout<<cnt[i]<<" ";cout<<" "; int cmd=counting();//cout<<cmd<<endl; if(cmd+deep<ans)ans=cmd+deep; for(int i=1;i<=10;++i)if(cnt[i]>=3) for(int j=i+1;j<=12;++j){ bool tag=0; for(int k=i;k<=j;++k) if(cnt[k]<3){ tag=1; break; } if(tag)break; for(int k=i;k<=j;++k)cnt[k]-=3; dfs(deep+1); for(int k=i;k<=j;++k)cnt[k]+=3; } for(int i=1;i<=10;++i)if(cnt[i]>=2) for(int j=i+2;j<=12;++j){ bool tag=0; for(int k=i;k<=j;++k) if(cnt[k]<2){ tag=1; break; } if(tag)break; for(int k=i;k<=j;++k)cnt[k]-=2; dfs(deep+1); for(int k=i;k<=j;++k)cnt[k]+=2; } for(int i=1;i<=8;++i) for(int j=i+4;j<=12;++j){ bool tag=0; for(int k=i;k<=j;++k) if(!cnt[k]){ tag=1; break; } if(tag)break; for(int k=i;k<=j;++k)--cnt[k]; dfs(deep+1); for(int k=i;k<=j;++k)++cnt[k]; } } int main(){ scanf("%d%d",&t,&n); while(t--){ memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;++i){ scanf("%d%d",&a,&b); if(a>=3||a<=13)cnt[a-2]++; if(a==0)cnt[14]++; if(a==1)cnt[12]++; if(a==2)cnt[13]++; } ans=0x3f3f3f3f; dfs(0); printf("%d ",ans); } return 0; }