LOJ2422 NOIP2015 斗地主 【搜索+贪心】*
LOJ2422 NOIP2015 斗地主
题目大意很简单,就是问你斗地主的一分手牌最少多少次出完
然后我们发现对于一种手牌状态,不考虑顺子的情况是可以贪心做掉的
然后我们直接枚举一下顺子出牌情况就可以了
LOJ上的数据随便写点基本贪心就行了
如果想过UOJ上的加强版的话还是把中间那一部分毒瘤的特判更优情况加上吧
当然也有个Smallfat大神用DP做掉的
我感觉DP更严谨一些,但是毕竟贪心好写嘛
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 20 4 int n,ans,is; 5 int col[N],cnt[N],tmp[N]; 6 int cal(){ 7 for(int i=1;i<=4;i++)tmp[i]=cnt[i]; 8 int res=0; 9 while(tmp[4]&&tmp[2]>=2)res++,tmp[4]--,tmp[2]-=2; 10 while(tmp[4]&&tmp[1]>=2)res++,tmp[4]--,tmp[1]-=2; 11 // 12 while(tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]) res+=2,tmp[1]--,tmp[3]-=2,tmp[4]--; 13 while(!tmp[1]&&tmp[2]&&tmp[3]>=3&&!tmp[4]) res+=2,tmp[2]--,tmp[3]-=3; 14 while(tmp[1]&&tmp[2]&&tmp[3]&&tmp[4]>=2) res+=2,tmp[1]--,tmp[2]--,tmp[3]--,tmp[4]-=2; 15 while(tmp[1]&&tmp[2]&&!tmp[3]&&tmp[4]>=2) res+=2,tmp[1]--,tmp[2]--,tmp[4]-=2; 16 while(!tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]>=2)res+=2,tmp[3]-=2,tmp[4]-=2; 17 while(!tmp[1]&&!tmp[2]&&tmp[3]>=2&&tmp[4]) res+=2,tmp[3]-=2,tmp[4]--; 18 // 19 while(tmp[4]&&tmp[2])res++,tmp[4]--,tmp[2]--; 20 while(tmp[4]>=2)res++,tmp[4]-=2; 21 while(tmp[3]&&tmp[2])res++,tmp[3]--,tmp[2]--; 22 while(tmp[3]&&tmp[1])res++,tmp[3]--,tmp[1]--; 23 if(is&&tmp[1]>=2)tmp[1]-=2,res++; 24 return res+tmp[1]+tmp[2]+tmp[3]+tmp[4]; 25 } 26 bool check(int l,int r,int num){ 27 for(int i=l;i<=r;i++)if(col[i]<num)return 0; 28 return 1; 29 } 30 void modify(int l,int r,int num){ 31 for(int i=l;i<=r;i++){ 32 cnt[col[i]]--; 33 col[i]+=num; 34 cnt[col[i]]++; 35 } 36 } 37 void dfs(int step){ 38 if(step>=ans)return; 39 ans=min(ans,step+cal()); 40 for(int l=2;l<=13;l++){ 41 for(int len=5;len+l-1<=13;len++){ 42 int r=len+l-1; 43 if(!check(l,r,1))break; 44 modify(l,r,-1); 45 dfs(step+1); 46 modify(l,r,1); 47 } 48 } 49 for(int l=2;l<=13;l++){ 50 for(int len=3;len+l-1<=13;len++){ 51 int r=len+l-1; 52 if(!check(l,r,2))break; 53 modify(l,r,-2); 54 dfs(step+1); 55 modify(l,r,2); 56 } 57 } 58 for(int l=2;l<=13;l++){ 59 for(int len=2;len+l-1<=14;len++){ 60 int r=len+l-1; 61 if(!check(l,r,3))break; 62 modify(l,r,-3); 63 dfs(step+1); 64 modify(l,r,3); 65 } 66 } 67 } 68 void solve(){ 69 int op,x;ans=n; 70 for(int i=0;i<=13;i++)col[i]=0,cnt[i]=0; 71 for(int i=1;i<=n;i++){ 72 scanf("%d%d",&op,&x); 73 if(op>1)op--; 74 else if(op)op=13; 75 col[op]++; 76 } 77 for(int i=1;i<=13;i++)if(col[i])cnt[col[i]]++; 78 cnt[1]+=col[0]; 79 is=(col[0]==2); 80 dfs(0); 81 printf("%d\n",ans); 82 } 83 int main(){ 84 int T;scanf("%d%d",&T,&n); 85 while(T--)solve(); 86 return 0; 87 }