题解 | #雀魂启动!#

雀魂启动!

https://www.nowcoder.com/practice/448127caa21e462f9c9755589a8f2416?tpId=137&tqId=33897&ru=/exam/oj

#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")

全部评论

相关推荐

10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务