牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。
具体规则如下:
Input
第一行包含用空格隔开的2个正整数Tn,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。 特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
Output
共T行,每行一个整数,表示打光第i手牌的最少次数。
Sample Input
样例输入1:
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
样例输入2:
1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
Sample Output
样例输出1:
3
样例输出2:
6
这个题目可以用贪心搜索解决,对于每次枚举,我们总是先枚举顺子,尽量把牌打的多,之后的最优性剪枝就可以发挥出较大的作用了,
不过,还是有点难实现,不会的话看看代码吧:
#include<iostream> #include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> using namespace std; int num[100]; int n,t,ans; int h[5]; int suan(){ int sum=0; memset(h,0,sizeof(h)); for(int i=0;i<=14;i++){ if(i==1) continue; h[num[i]]++; } while(h[4]>0&&h[2]>1) h[4]--,h[2]-=2,sum++; while(h[4]>0&&h[1]>1) h[4]--,h[1]-=2,sum++; while(h[3]>0&&h[2]>0) h[3]--,h[2]--,sum++; while(h[3]>0&&h[1]>0) h[3]--,h[1]--,sum++; return sum+h[4]+h[3]+h[2]+h[1]; } void dfs(int now){ if(now>=ans) return; for(int star=3;star<=14;star++){ if(num[star]>=3){ int end=15; for(int j=star+1;j<=14;j++) if(num[j]<3) {end=j;break;} if(end-star<2) continue; for(int k=end-star;k>=2;k--){ for(int i=star;i<star+k;i++) num[i]-=3; dfs(now+1); for(int i=star;i<star+k;i++) num[i]+=3; } } } for(int star=3;star<=14;star++){ if(num[star]>=2){ int end=15; for(int j=star+1;j<=14;j++) if(num[j]<2) {end=j;break;} if(end-star<3) continue; for(int k=end-star;k>=3;k--){ for(int i=star;i<star+k;i++) num[i]-=2; dfs(now+1); for(int i=star;i<star+k;i++) num[i]+=2; } } } for(int star=3;star<=14;star++){ if(num[star]>=1){ int end=15; for(int j=star+1;j<=14;j++) if(num[j]<1) {end=j;break;} if(end-star<5) continue; for(int k=end-star;k>=5;k--){ for(int i=star;i<star+k;i++) num[i]-=1; dfs(now+1); for(int i=star;i<star+k;i++) num[i]+=1; } } } int tot=suan(); ans=min(ans,tot+now); return; } int main(){ cin>>t>>n; for(int q=1;q<=t;q++){ memset(num,0,sizeof(num)); ans=1<<30; for(int i=1;i<=n;i++){ char x[2],y[2]; int len; cin>>x>>y; len=strlen(x); if(len==1){ if(x[0]=='1') num[14]++; else num[x[0]-'0']++; } else{ if(x[0]=='0') num[0]++; else num[10+x[1]-'0']++; } } dfs(0); printf("%d ",ans); } }