【题目大意】
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
【思路】
搜索+剪枝。统计每种数字出现的次数,先算顺子。
注意双王算作对子。
1 #include<iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int MAXN= 18; 7 8 int calc(int x[]) 9 { 10 memset(cnt, 0, sizeof(cnt)); 11 int res=0; 12 for(int i=0;i<maxn;i++) cnt[x[i]]++; 13 while(cnt[4]&& cnt[2]>= 2) res++,cnt[4]--,cnt[2]-=2; 14 while(cnt[4]&& cnt[1]>= 2) res++,cnt[4]--,cnt[1]-=2; 15 while(cnt[3]&& cnt[2]>= 1) res++,cnt[3]--,cnt[2]-=1; 16 while(cnt[3]&& cnt[1]>= 1) res++,cnt[3]--,cnt[1]-=1; 17 return res+cnt[1]+cnt[2]+cnt[3]+cnt[4]; 18 } 19 20 void dfs(intx[],intstep) 21 { 22 if(step>ans)return; 23 ans=min(ans,step+calc(x)); 24 for(int i=2,j;i<maxn;i++) 25 { 26 for(j=i;x[j]>=3;j++); 27 if(j-i>=2) 28 { 29 for(int t=j;t-i>=2;t--) 30 { 31 for(intk=i;k<t;k++)x[k]-=3; 32 dfs(x,step+1); 33 for(intk=i;k<t;k++)x[k]+=3; 34 } 35 } 36 } 37 for(int i=2,j;i<maxn;i++) 38 { 39 for(j=i;x[j]>=2;j++); 40 if(j-i>=3){ 41 for(int t=j;t-i>=3;t--) 42 { 43 for(intk=i;k<t;k++)x[k]-=2; 44 dfs(x,step+1); 45 for(intk=i;k<t;k++)x[k]+=2; 46 } 47 } 48 } 49 for(int i=2,j;i<maxn;i++) 50 { 51 for(j=i;x[j]>=1;j++); 52 if(j-i>=5){ 53 for(int t=j;t-i>=5;t--){ 54 for(intk=i;k<t;k++)x[k]-=1; 55 dfs(x,step+1); 56 for(intk=i;k<t;k++)x[k]+=1; 57 } 58 } 59 } 60 } 61 62 int main() 63 { 64 scanf("%d%d",&T,&n); 65 while(T--) 66 { 67 memset(a,0,sizeof(a)); 68 for(int i=1;i<=n;i++) 69 { 70 intw=iread(),c=iread(); 71 if(w==1)w=13; 72 elseif(w)w--; 73 a[w]++; 74 } 75 ans=calc(a); 76 dfs(a,0); 77 printf("%d\n",ans); 78 } 79 return0; 80 }
时间: 2024-10-18 21:04:51