算法

回溯算法(递归)

思路

如果手中的14张牌是能和牌的,那么这14张牌分别参与雀头、顺子、刻子。进一步,把牌分成两部分,遍历牌数大于二的牌,让这些牌作为雀头,对剩下的牌,要么参与顺子的构造,要么参与刻子的构造。
根据这样的分析,分两层回溯算法。
特别的,对于牌数是4的牌,有两种组合方法:这四张牌参与到四个顺子中或者这四张牌中三张作为刻子,另外一张参与一个顺子

代码

#include<iostream>
#include<vector>
using namespace std;
bool check_cards(int* cards, int k) {

    if (k == 9)
        return true;

    if (cards[k] == 0)
        return check_cards(cards, k + 1);

    int temp = cards[k];
    for (int i = k - 2; i <= k; i++) {
        if (i >= 0 && i + 2 < 9
            && cards[i] >= temp && cards[i + 1] >= temp && cards[i + 2] >= temp) {
            cards[i] -= temp;
            cards[i + 1] -= temp;
            cards[i + 2] -= temp;

            if (check_cards(cards, k + 1))
                return true;

            cards[i] += temp;
            cards[i + 1] += temp;
            cards[i + 2] += temp;
        }
    }

    if (temp == 3) {
        cards[k] -= 3;
        if (check_cards(cards, k + 1))
            return true;
        cards[k] += 3;
    }

    if (temp == 4) {
        temp = 1;
        for (int i = k - 2; i <= k; i++) {
            if (i >= 0 && i + 2 < 9
                && cards[i] >= temp && cards[i + 1] >= temp && cards[i + 2] >= temp) {
                cards[i] -= temp;
                cards[i + 1] -= temp;
                cards[i + 2] -= temp;
                cards[k] -= 3;

                if (check_cards(cards, k + 1))
                    return true;

                cards[i] += temp;
                cards[i + 1] += temp;
                cards[i + 2] += temp;
                cards[k] += 3;
            }
        }
    }
    return false;
}
int main(void) {
    int cards[9] = { 0 }, cards_bk[9] = { 0 };
    for (int i = 0; i < 13; i++) {
        int j;
        cin >> j;
        cards[j - 1]++;
    }
    for (int i = 0; i < 9; i++)
        cards_bk[i] = cards[i];
    vector<int> oks;
    for (int i = 0; i < 9; i++) {
        if (cards[i] == 4)
            continue;
        for (int i = 0; i < 9; i++)
            cards[i] = cards_bk[i];
        cards[i]++;
        int ok = 0;
        for (int j = 0; j < 9 && !ok; j++) {
            //取雀头-对j
            if (cards[j] < 2)
                continue;

            cards[j] -= 2;
            if (check_cards(cards, 0)) {
                ok = 1;
                oks.push_back(i + 1);
            }
            cards[j] += 2;
        }

        cards[i]--;
    }
    if (oks.size() == 0)
        cout << 0;
    else
        for (int i = 0; i < oks.size(); i++) {
            cout << oks[i];
            if (i != oks.size() - 1)
                cout << ' ';
        }

}