#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
vector<int> res;
bool is_valid(vector<int>& cards) {
//继续穷举
for (int i = 1; i <= 9; i++) {
//先找顺子
if (cards[i] >= 3) {
cards[i] -= 3;
//递归,如果剩余的牌能够和牌,返回true
//递归,如果剩余的牌能够和牌,返回true
if (is_valid(cards)) {
//回溯
cards[i] += 3;
return true;
}
//回溯
cards[i] += 3;
}
//再找刻子
if (i <= 7 && cards[i] > 0 && cards[i + 1] > 0 && cards[i + 2] > 0) {
cards[i]--;
cards[i + 1]--;
cards[i + 2]--;
//递归,如果剩余的牌能够和牌,返回true
if (is_valid(cards)) {
//回溯
cards[i]++;
cards[i + 1]++;
cards[i + 2]++;
return true;
}
//回溯
cards[i]++;
cards[i + 1]++;
cards[i + 2]++;
}
}
//走到这里有两种可能:
// 1、有剩下的牌 -- 无法和牌返回false
// 2、没剩下牌 -- 和牌返回true
for (int i = 1; i <= 9; i++) {
if (cards[i] > 0) {
return false;
}
}
return true;
}
bool head(vector<int>& cards) {
//如果有两张一样的牌,先尝试作为雀头
for (int i = 1; i <= 9; i++) {
if (cards[i] >= 2) {
cards[i] -= 2;
//再用递归回溯从,剩余牌中找顺子和刻子,如果能和牌,代表这次抽取成功,打印记录
if (is_valid(cards)) {
//回溯 -- 这里return了就不走到71行回溯,那么找下一种组合的时候就会少两张牌,大漏洞
//同理后面找顺子刻子也要先回溯再returen
cards[i] += 2;
return true;
}
//回溯
cards[i] += 2;
}
}
//走到这代表没有雀头,寄
return false;
}
void check(vector<int>& cards) {
//抽一张,穷举法
for (int i = 1; i <= 9; i++) {
//如果有一张牌的数量小于4,代表可以抽这张牌,进行穷举
if (cards[i] < 4) {
//抽取
cards[i]++;
//继续穷举选择雀头
if (head(cards)) {
res.push_back(i);
}
//回溯
cards[i]--;
}
}
}
int main() {
//哈希表存放已有的牌
vector<int> cards(10);
//抽取13张牌
for(int i=0;i<13;i++){
int n;
cin>>n;
cards[n]++;
}
//回溯法检查和牌
check(cards);
//防止顺序不一样,排下序 -- res是全局变量,懒得传参了
sort(res.begin(),res.end());
for(auto v : res){
cout << v <<" ";
}
return 0;
}
// 64 位输出请用 printf("%lld")