所有元数从小到大排列,尝试插入1到9,插入前检查当前数字的个数,确保插入后不会超过4。一定会出现雀头,尝试去掉雀头再打牌,剩下的牌则看是否为刻子、顺子,是则打掉牌,再打剩下的牌。若所有的牌都能打完则当前插入的数可胡牌。

#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
bool is_hu(const vector<int>& vec)
{
    //所有的牌都能打完则胡牌;
    if(vec.size() == 0)
        return true;

    int n = vec.size();
    multiset<int> m_set(vec.begin(),vec.end());
    int count0 = m_set.count(vec[0]);
    //没有现出过雀头并且第一个数出现2次或者以上;
    if(n % 3 != 0 && count0 >= 2)
    {
        //试着将雀头打掉,看剩下的牌能否打完;
        vector<int> tmp(vec.begin()+2,vec.end());
        if(is_hu(tmp))
            return true;
    }

    //如果第一个数字出现次数 >= 3,试着打掉这个刻子后看剩下的是否能够打完;
    if(count0 >= 3)
    {
        vector<int> tmp(vec.begin()+3,vec.end());
        if(is_hu(tmp))
            return true;
    }

    //如果存在顺子,打掉顺子后剩下看是否能各牌;
    if(m_set.find(vec[0]+1) != m_set.end() && m_set.find(vec[0]+2) != m_set.end())
    {
        vector<int> tmp(vec);
        vector<int>::iterator iter = std::find(tmp.begin(),tmp.end(),vec[0]);
        if(iter != tmp.end())
            tmp.erase(iter);

        iter = std::find(tmp.begin(),tmp.end(),vec[0]+1);
        if(iter != tmp.end())
            tmp.erase(iter);

        iter = std::find(tmp.begin(),tmp.end(),vec[0]+2);
        if(iter != tmp.end())
            tmp.erase(iter);

        if(is_hu(tmp))
            return true;
    }
    return false;
}

int main()
{
    vector<int> vec;
    int n;
    while(cin >> n)
        vec.push_back(n);

    for(int i=1;i<=9;i++)
    {
        vector<int> tmp(vec);
        //最多只有四张相同的牌,插入后不能超过4,这里做下判断;
        multiset<int> m_set(tmp.begin(),tmp.end());
        if(m_set.count(i) >= 4)
        {
            continue;
        }

        tmp.push_back(i);
        sort(tmp.begin(),tmp.end());
        if(is_hu(tmp))
            cout << i << " ";
    }

    return 0;
}