- 三层递归。(回溯)
- 扑克牌转换成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; }