版权声明:欢迎转载,请注明出处,谢谢 https://blog.csdn.net/Dream_maker_yk/article/details/82702191
LOJ2422 NOIP2015 斗地主
题目大意很简单,就是问你斗地主的一分手牌最少多少次出完
然后我们发现对于一种手牌状态,不考虑顺子的情况是可以贪心做掉的
然后我们直接枚举一下顺子出牌情况就可以了
LOJ上的数据随便写点基本贪心就行了
如果想过UOJ上的加强版的话还是把中间那一部分毒瘤的特判更优情况加上吧
当然也有个Smallfat大神用DP做掉的
我感觉DP更严谨一些,但是毕竟贪心好写嘛
#include<bits/stdc++.h>
using namespace std;
#define N 20
int n,ans,is;
int col[N],cnt[N],tmp[N];
int cal(){
for(int i=1;i<=4;i++)tmp[i]=cnt[i];
int res=0;
while(tmp[4]&&tmp[2]>=2)res++,tmp[4]--,tmp[2]-=2;
while(tmp[4]&&tmp[1]>=2)res++,tmp[4]--,tmp[1]-=2;
//
while(tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]) res+=2,tmp[1]--,tmp[3]-=2,tmp[4]--;
while(!tmp[1]&&tmp[2]&&tmp[3]>=3&&!tmp[4]) res+=2,tmp[2]--,tmp[3]-=3;
while(tmp[1]&&tmp[2]&&tmp[3]&&tmp[4]>=2) res+=2,tmp[1]--,tmp[2]--,tmp[3]--,tmp[4]-=2;
while(tmp[1]&&tmp[2]&&!tmp[3]&&tmp[4]>=2) res+=2,tmp[1]--,tmp[2]--,tmp[4]-=2;
while(!tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]>=2)res+=2,tmp[3]-=2,tmp[4]-=2;
while(!tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]) res+=2,tmp[3]-=2,tmp[4]--;
//
while(tmp[4]&&tmp[2])res++,tmp[4]--,tmp[2]--;
while(tmp[4]>=2)res++,tmp[4]-=2;
while(tmp[3]&&tmp[2])res++,tmp[3]--,tmp[2]--;
while(tmp[3]&&tmp[1])res++,tmp[3]--,tmp[1]--;
if(is&&tmp[1]>=2)tmp[1]-=2,res++;
return res+tmp[1]+tmp[2]+tmp[3]+tmp[4];
}
bool check(int l,int r,int num){
for(int i=l;i<=r;i++)if(col[i]<num)return 0;
return 1;
}
void modify(int l,int r,int num){
for(int i=l;i<=r;i++){
cnt[col[i]]--;
col[i]+=num;
cnt[col[i]]++;
}
}
void dfs(int step){
if(step>=ans)return;
ans=min(ans,step+cal());
for(int l=2;l<=13;l++){
for(int len=5;len+l-1<=13;len++){
int r=len+l-1;
if(!check(l,r,1))break;
modify(l,r,-1);
dfs(step+1);
modify(l,r,1);
}
}
for(int l=2;l<=13;l++){
for(int len=3;len+l-1<=13;len++){
int r=len+l-1;
if(!check(l,r,2))break;
modify(l,r,-2);
dfs(step+1);
modify(l,r,2);
}
}
for(int l=2;l<=13;l++){
for(int len=2;len+l-1<=14;len++){
int r=len+l-1;
if(!check(l,r,3))break;
modify(l,r,-3);
dfs(step+1);
modify(l,r,3);
}
}
}
void solve(){
int op,x;ans=n;
for(int i=0;i<=13;i++)col[i]=0,cnt[i]=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&op,&x);
if(op>1)op--;
else if(op)op=13;
col[op]++;
}
for(int i=1;i<=13;i++)if(col[i])cnt[col[i]]++;
cnt[1]+=col[0];
is=(col[0]==2);
dfs(0);
printf("%d\n",ans);
}
int main(){
int T;scanf("%d%d",&T,&n);
while(T--)solve();
return 0;
}