所有元数从小到大排列,尝试插入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; }