在知乎上看到乙個問題,如何用程式判斷麻將牌是否和牌。和牌的規則為:14張麻將牌當中,必須要有乙個對子,即兩張相同的牌,除去對子後,剩下的牌可以組合成」a, a, a」或者」a, a+1, a+2」兩種模式的組合,其中a為某種花色的某張牌。
我的解法是:
首先定義一下麻將牌在程式中的表示方式:
把萬,餅,條分別用連續的數字代表,比如:一萬到九萬用1到9表示,一餅到九餅用11到19表示,一條到九條用21到29表示。重要的是每一種牌內部數字是連續的,不同牌之間的數字不連續。對於風和中發白,每一種都用互相之間不連續的數字表示,比如中是31,發是33,白是35等等。
由於和牌中必需要有乙個對子,所以我們的思路是,去除可能的對子,然後判斷剩下的牌是否可以表示成「a a a」或者「a a+1 a+2 」這兩種模式的組合。
具體流程是:對輸入的14張麻將牌序列進行排序,排序後,由低到高依次尋找對子,如果佇列中沒有對子,那麼肯定不是和牌,程式結束。找到對子後,將這兩張對子從序列中刪除,判斷其餘的牌是否滿足下面的條件,如果滿足,則為和牌,結束,如果不滿足,則在排序後的輸入佇列中尋找下乙個對子,重複本過程,直到條件1滿足或者搜尋到序列結尾。
條件1:序列中的元素可以分為每3個元素一組,每組元素均為「a a a」或者「a a+1 a+2 」的形式。為了判斷乙個序列是否滿足條件1,我們觀察到以下幾個性質:
性質1:排序後的麻將牌序列可以分割成若干子串行,其中每個子串行內部的元素是連續的,且不同序列間的元素不連續(連續指相鄰元素的值相同或值相差1)。於是,我們下一步要做的事情就是,將排序後的序列按照連續性分組,然後遞迴判斷每組是否滿足條件1,如果所有組都滿足條件1,則分組前序列也滿足條件1,否則不滿足。性質2:排序後的麻將牌序列滿足條件1的充分必要條件是,按性質1分割的每個子串行均滿足條件1。
性質3:如果乙個序列滿足條件1,則按性質1分割後的子串行元素個數必定為3的整數倍。
為了判斷乙個連續序列是否滿足條件1,可以分幾種情況考慮:
1. 如果序列中有3個元素,則直接判斷是否屬於條件1中的兩種情況即可;
否則,設a為序列中的最小值,
2. 如果a的個數大於等於3(即3或4),則序列滿足條件1的充分必要條件是序列去掉3個a後的剩餘元素滿足條件1;
3. 如果a的個數小於3(即1或2),則序列滿足條件1的充分必要條件是序列去掉(a, a+1, a+2)後的剩餘元素滿足條件1;
時間複雜度:
由於牌的個數是常數14,且每輪迭代資料規模都會減小,因此,該演算法時間複雜度為o(1)。
**:
#include
#include
#include
using
namespace
std;
static
vector
result;
//for debug
void prtvct(const
vector
&v, bool nxtline = true)
if (nxtline)
cout
<< endl;
}bool erase_by_val(vector
&in, int val)
}return
false;
}void push_result(int a, int b, int c)
bool shrink(vector
&in) else
}int i, t;
for (i = 0, t = in[0]; i < 3; ++i, ++t)
push_result(t-3, t-2, t-1);
return
true;
}void group(vector
&input, vector
> &grp) else
for (auto it = input.begin()+1; it != input.end(); ++it)
grp.push_back(member);
member.clear();
member.push_back(*it);
}grp.push_back(member);
}bool islegal(vector
&input)
if (input.size() == 3)
if (input[1] == input[0] + 1 && input[2] == input[1] + 1)
return
false;
}group(input, grp);
// for each group
for (auto it = grp.begin(); it != grp.end(); ++it)
if (islegal(*it) == false)
}return
true;
}bool ishu(vector
&input)
}do while (i < input.size()-1 && input[i] == input[i-1]);
}return
false;
}int main()
if (ishu(input)) else
}return
0;}
實現麻將牌發牌操作
import random class card 建立5個列表,總牌堆和四名玩家各乙個牌堆 cards player1 player2 player3 player4 def init self,name self.name name def str self return self.name 使用...
麻將胡牌判決
胡牌有以下幾種情況 1 乙個對子 4組 3個相同的牌或者順子。只有m s p是可以構成順子的。東西南北這樣的牌沒有順子。2 7個不同的對子。3 1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.這13種牌每種都有,而且僅有這13種牌。肯定是有一種2張。其他的1張。首先是列...
麻將胡牌判決
就是給了13張牌。問增加哪些牌可以胡牌。胡牌有以下幾種情況 1 乙個對子 4組 3個相同的牌或者順子。只有m s p是可以構成順子的。東西南北這樣的牌沒有順子。2 7個不同的對子。3 1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.這13種牌每種都有,而且僅有這13種牌...