首先如果对子和三张牌出现在解中,那么全拆成单张显然没有问题,顺子同理。于是真正有用的牌型就只有单牌、三带一、三带二、四带二了。
暴搜jry手中的牌,然后先搜出双方的大牌型(即三张、四张牌的个数),再枚举三张牌带了几个对子,剩下的三张牌和四张牌带的都是单牌。这些被带的对子和单牌是没有大小限制的,所以对于jry手中的牌,应尽量带掉大牌,网友应尽量带掉小牌,这样才能尽量存在解。
最后剩的都是单牌了,扫一遍判断是否合法即可,总的来说没有坑点。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 using namespace std; 5 6 const int N=20; 7 int ans,g[300],a[N],b[N],c[N],d[N],e[N]; 8 char s[N]; 9 10 int F(char c){ return (c>='4' && c<='9') ? c-'4' : g[(int)c]; } 11 12 bool work(int o,int p){ 13 rep(i,0,o){ 14 int x=o+p-i,y=i; 15 rep(j,0,13) d[j]=c[j]; 16 for (int j=13; ~j; j--){ 17 while (y && d[j]>=2) d[j]-=2,y--; 18 while (x && d[j]) d[j]--,x--; 19 } 20 if (x|y) continue; 21 rep(j,0,13) e[j]=a[j]; 22 x=o+p-i,y=i; 23 rep(j,0,13){ 24 while (y && e[j]>=2) e[j]-=2,y--; 25 while (x && e[j]) e[j]--,x--; 26 } 27 if (x|y) continue; 28 x=0; bool flag=0; 29 rep(j,0,13){ 30 if (e[j]>x){ flag=1; break; } 31 x+=d[j]-e[j]; 32 } 33 if (!flag) return 1; 34 } 35 return 0; 36 } 37 38 bool solve(int x,int o,int p,int q,int r){ 39 if (x==14) return !q && !r && work(o,p); 40 bool f; 41 if (c[x]>=4){ 42 c[x]-=4; f=solve(x+1,o,p+2,q,r+1); c[x]+=4; 43 if (f) return 1; 44 } 45 if (c[x]>=3){ 46 c[x]-=3; f=solve(x+1,o+1,p,q+1,r); c[x]+=3; 47 if (f) return 1; 48 } 49 if (a[x]>=4 && r){ 50 a[x]-=4; f=solve(x+1,o,p,q,r-1); a[x]+=4; 51 if (f) return 1; 52 } 53 if (a[x]>=3 && q){ 54 a[x]-=3; f=solve(x+1,o,p,q-1,r); a[x]+=3; 55 if (f) return 1; 56 } 57 return solve(x+1,o,p,q,r); 58 } 59 60 void dfs(int x,int s){ 61 if (x==14){ if (!s && solve(0,0,0,0,0)) ans++; return; } 62 rep(i,0,min(s,b[x])) c[x]=i,dfs(x+1,s-i); 63 } 64 65 int main(){ 66 g['T']=6,g['J']=7,g['Q']=8,g['K']=9,g['A']=10,g['2']=11,g['w']=12,g['W']=13; 67 scanf("%s",s); 68 rep(i,0,11) b[i]=4; b[12]=b[13]=1; 69 rep(i,0,16) a[F(s[i])]++,b[F(s[i])]--; 70 dfs(0,17); printf("%d ",ans); 71 return 0; 72 }