- 三层递归。(回溯)
- 扑克牌转换成hash的方式进行存储,以至于可以从每一个牌进行遍历。
#include<bits/stdc++.h>
using namespace std;
vector<int> card(9);//统计每个牌出现的次数
bool hasTrible(int n){
//base case
if(n==0) return true;//走完了,返回true
//检验是不是刻子或者是顺子(也是从头开始检查)
for(int i = 0; i< card.size();i++){
//因为仍是从1开始查验,因此若检查到其牌数>=3,则必定是刻子
if(card[i]>2){
//三层回溯(继续开始回溯)
card[i]-=3;
if(hasTrible(n-1)){ //检查余下的牌能否组成n-1个顺子或刻子
card[i]+=3;//恢复选择
return true;
}
card[i]+=3;
//否则只能是顺子(要有许多条件)
}else if(i< card.size()-2&& card[i]>0&& card[i+1]>0&& card[i+2]>0 ){
card[i]--;
card[i+1]--;
card[i+2]--;
if(hasTrible(n-1)){
card[i]++;
card[i+1]++;
card[i+2]++;
return true;
}
card[i]++;
card[i+1]++;
card[i+2]++;
}
}
return false;//全部找完,不行。结束
}
bool isWin(){
//base case;
for(int i=0; i< 9;i++){//依次把1~9作为雀头拿出来,检查剩下的12张牌能否顺或刻子
if(card[i]<2){//无法作为雀头(小剪枝)
continue;
}
// 继续回溯(二级回溯)
card[i]-=2;//检查剩下的12张牌能否顺或刻子
if(hasTrible(4)){//要有4组满足顺子或者是刻子的条件
//因为外面还有一层回溯,所以要撤销选择
card[i]+=2;
return true;
}
card[i]+=2;//回退
}
return false;
}
int main(){
vector<int> res;
int x;
for(int i =0; i< 13;i++){
cin>>x;
card[x-1]++; //统计出现的次数。(技巧,用索引替代牌面,然后统计)
}
//回溯
for(int i=0; i< 9;i++){//1~9依次添加,检查是否可以和牌(又可以满足从小到大的排序)
if(card[i]>3){//已经达到每张牌4张
continue;
}
//做选择
card[i]++;
if(isWin()){//带着选择入递归
res.push_back(i+1);
}
card[i]--;//撤销选择
}
if(res.empty()) cout<<0<<endl;
for(int i =0; i< res.size();i++){
if(i==res.size()-1){
cout<<res[i]<<endl;
}else{
cout<<res[i]<<" ";
}
}
return 0;
}