日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[算法] 麻将序数牌组合方案

發布時間:2023/12/9 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [算法] 麻将序数牌组合方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
// 環境: centos7.2, g++ v4.8.5#include <iostream> #include <unistd.h> #include <stdio.h> #include <string.h> #include <vector> #include <map>using namespace std;enum CombineType {CombineType_Null = 0, // 單牌CombineType_Dui = 1, // 對子CombineType_Ke = 2, // 刻CombineType_Shun = 3 // 順子 };struct Combine // 一種組合 {CombineType type;vector<int> cards;Combine(){type = CombineType_Null;} };map<int, vector<int>> classify(vector<int>& v) {map<int, vector<int>> m;for(auto& it : v){if(m.find(it) == m.end()){m[it] = {};}m[it].push_back(it);}#if 1for(auto& it : m){printf("%d: ", it.first);for(auto& it2 : it.second)printf("%d ", it2);printf("\n");} #endifreturn m; }// 從m中找一種符合組合類型為type的組合, 這個組合里最小的卡id為min Combine findCombine(map<int, vector<int>>& m, int min, CombineType type) {printf("開始查找: min=%d, type=%d\n", min, type);Combine comb;if(type == CombineType_Dui || type == CombineType_Ke) // 查找對子或刻{uint n = type == CombineType_Dui ? 2 : 3;if(m[min].size() >= n) // 能找到對子或刻{for(int i = 0; i < n; i++) // 從m[min]中取n張卡到comb.cards中{comb.cards.push_back(min);m[min].pop_back();if(m[min].empty())m.erase(min);}comb.type = type;}}else if(type == CombineType_Shun && min <= 7) // 8往后不可能組成順子了{if(m.find(min) != m.end() && m.find(min+1) != m.end() && m.find(min+2) != m.end()) // 找到以min開始的順子{comb.cards = {min, min+1, min+2};comb.type = type;for(auto& it : comb.cards){m[it].pop_back();if(m[it].empty())m.erase(it);}}}return comb; }void display(Combine comb) {printf("comb.type = %d, cards = ", comb.type);for(auto& it : comb.cards)printf("%d ", it);printf("\n\n"); }void displayCombines(vector<Combine>& v) {for(auto& it : v){for(auto& it2 : it.cards){printf(" %d", it2);}printf(",");}printf("\n\n"); }// vector<Combine>: 一種組合方案 // vector<vector<Combine>>: 多種組合方案 vector<vector<Combine>> getCombines(vector<int>& v) {vector<vector<Combine>> ret;auto m = classify(v);auto firstCard = [&m]() // 查找m中鍵最小的那個數{for(auto& it : m){return it.first;}return 0;};auto useCombine = [&m](Combine& comb) // 使用組合{for(auto& it : comb.cards) // 從m中刪除comb中的卡牌{m[it].pop_back();if(m[it].empty())m.erase(it);}};auto recyle = [&m](Combine& comb) // 回收comb中的卡牌{for(auto& it : comb.cards){if(m.find(it) == m.end()){m[it] = {};}m[it].push_back(it);}};printf("\n開始查找新的組合方案-----------------\n");vector<Combine> stack;int min = firstCard();CombineType oldType = CombineType_Null; // 下次從此類型之后開始找do{bool b = false;auto types = {CombineType_Dui, CombineType_Ke, CombineType_Shun};for(auto& it : types){if(it <= oldType) // 以前找過的組合類型, 不再繼續尋找continue;auto comb = findCombine(m, min, it);if(comb.type == it) // 找到一個組合{stack.push_back(comb);b = true;break;}}if(b) {printf("找到一個組合: ");display(stack.back());if(m.empty()) // 找到一種組合方案(牌分配完了){ret.push_back(stack);printf("【找到一種組合方案】:");displayCombines(stack);}else{auto tmp = min;min = firstCard(); // 確定下次要找的牌if(tmp != min)oldType = CombineType_Null; // 下次查找的類型重置}}else if(!stack.empty()) // 有可回收的組合(回歸查找準備) {auto comb = stack.back(); // 取(復制)棧頂元素oldType = comb.type; // 記錄上次此組合開始查找的類型min = comb.cards[0]; // 下次從此牌開始找printf("回收一個組合: ");display(comb);recyle(comb); // 回收棧頂元素中的卡牌stack.pop_back(); // 彈出棧頂組合}else // 沒有可回收的組合(即方案尋找結束)break;}while(true);return ret; }int main() {//vector<int> v = {1, 1, 1, 2, 2, 2, 8, 8};vector<int> v = {1, 1, 2, 4, 5, 6};auto vvc = getCombines(v);printf("--------------------------------\n");printf("vvc.size=%d\n", vvc.size());for(auto& vc : vvc){for(auto& comb : vc){printf("%d: ", comb.type);for(auto& c : comb.cards)printf("%d ", c);printf("\n");}printf("\n");}return 0; }


以上代碼是模擬麻將的序數牌,如萬、筒、條,將同是萬字的牌按對子、刻、順子去組合, 列出所有可能的組合!


總結

以上是生活随笔為你收集整理的[算法] 麻将序数牌组合方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。