hihocoder #1503 : 一人麻将

    xiaoxiao2021-04-14  57

    时间限制: 10000ms 单点时限: 1000ms 内存限制: 256MB

    描述

    小Hi在北方的暖气里温暖如春,小Ho却在南方的艳阳里感受大雪纷飞。距离使得他们连一起打麻将的机会都没有,失落的小Hi一个人玩起了麻将。

    小Hi玩的是四川麻将,因此只有3种序数牌万、筒、条,每种花色一到九各4张。

    小Hi起手拥有14张牌,之后小Hi每摸一张牌后,如果没有胡牌,就出一张牌,直至胡牌或牌被摸光。反正一个人玩又赢不到小Ho的钱,因此小Hi永远也不会选择暗杠。

    胡牌的规则如下:

    手中14张牌最多只能属于两个花色。

    手中14张牌的牌型须满足下列两个条件之一:

    1)3 + 3 + 3 + 3 + 2,其中的3代表一坎(指同花色且同数字、或同花色且数字相连的三张牌),其中的2代表一个对子(指两张同花色且同数字的牌)。

    2)2 × 7,即14张牌构成7个对子,特别的,四张花色数字全相同的牌可以看作两个对子。 万、筒、条分别记为a, b, c,以下对能胡牌的牌型举出一些例子:

    a1 a2 a3 a5 a5 a5 c3 c4 c5 c5 c6 c7 c7 c7

    b2 b2 b5 b5 b7 b7 b8 b8 c1 c1 c2 c2 c3 c3

    现给出小Hi的起手牌,并按顺序给出场上其余小Hi将要摸的牌。(小Hi只拿出了一副麻将的一部分牌玩,因此并不是每张牌都会被摸到。)

    请计算小Hi最早在摸第几张牌之后就可能胡牌,天胡(起手牌构成胡牌牌型)记为第0张。无法胡牌输出-1。

    输入

    每张牌用a, b或c其后紧接一个数字1-9表示。

    第一行是一个正整数n (n <= 94),代表将要摸的牌。

    第二行是14张手牌。

    第三行是n张底牌,按摸牌顺序给出。

    输出

    输出一个整数,代表最早在摸第几张牌之后可能胡牌,无法胡牌输出-1。

    样例输入 12 a1 a1 a1 a2 a3 a4 a5 a6 a7 a8 a9 a9 a9 c1 c2 b1 b2 b4 b5 c1 b7 b8 a1 a2 a3 a4 样例输出 6

    ..

    不敢搜啊,其实算算搜索深度只有4层,还是可以无脑搜的

    每一层节点得选取无非是 123连着的 或者三个重复的

    到达第四层后 看看是否有对子即可

    特判一下七小对

    参考网上代码的实现:

    #include<bits/stdc++.h> using namespace std; typedef long long ll; const int size = 255; int cnt[3][10]; int k1,k2; bool ok1_sub(int dep) { if (dep>4) { for(int i=1;i<=9;i++) if (cnt[k1][i]>=2) return true; for(int i=1;i<=9;i++) if (cnt[k2][i]>=2) return true; return false; } for(int i=1;i<=9;i++) { if (cnt[k1][i]>=3) { cnt[k1][i]-=3; if (ok1_sub(dep+1)) return true; cnt[k1][i]+=3; } } for(int i=1;i<=9;i++) { if (cnt[k2][i]>=3) { cnt[k2][i]-=3; if (ok1_sub(dep+1)) return true; cnt[k2][i]+=3; } } for(int i=1;i<=7;i++) { if (cnt[k1][i]&&cnt[k1][i+1]&&cnt[k1][i+2]) { cnt[k1][i]--,cnt[k1][i+1]--,cnt[k1][i+2]--; if (ok1_sub(dep+1)) return true; cnt[k1][i]++,cnt[k1][i+1]++,cnt[k1][i+2]++; } } for(int i=1;i<=7;i++) { if (cnt[k2][i]&&cnt[k2][i+1]&&cnt[k2][i+2]) { cnt[k2][i]--,cnt[k2][i+1]--,cnt[k2][i+2]--; if (ok1_sub(dep+1)) return true; cnt[k2][i]++,cnt[k2][i+1]++,cnt[k2][i+2]++; } } return false; } bool ok1() { for(k1=0;k1<=2;k1++) for( k2=k1;k2<=2;k2++) if (ok1_sub(1)) return true; return false; } bool ok2() { int num[3]; for(int i=0;i<=2;i++) { num[i]=0; for(int j=1;j<=9;j++)num[i]+=cnt[i][j]/2; } if (num[0]+num[1]>=7)return true; if (num[2]+num[1]>=7)return true; if (num[2]+num[0]>=7)return true; return false; } int main() { int n; cin>>n; char ss[4]; for(int i=1; i<=14; i++) { scanf("%s",ss); cnt[ ss[0]-'a' ][ss[1]-'0']++; } if (ok1()||ok2()) { return printf("0\n") ,0; } for(int i=1; i<=n; i++) { scanf("%s",ss); cnt[ ss[0]-'a' ][ss[1]-'0']++; if (ok1()||ok2()) return printf("%d\n",i) ,0; } return printf("-1\n"),0; return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-670021.html

    最新回复(0)