題目描述:
清一色是麻將番種之一,指由一種花色的序數牌組成的和牌.
數字1-9,每個數字最多有4張牌
我們不考慮具體花色,我們只看數字組合。
刻子:三張一樣的牌;如: 111, 222, 333, …, 999
順子:三張連續的牌;如: 123, 234, 345, …, 789
對子:兩張相同的牌;如: 11, 22, 33, …, 99
需要實現一個程序,判斷給定牌,是否可以和牌(胡牌)。
和牌要求:
麻將牌張數只能是 2, 5, 8, 11, 14
給定牌可以組合成,除1個對子以外其他都是刻子或順子
舉例: - “11” -> “11”, 1對子,可以和牌
“11122233” -> “111”+“222”+“33”, 2刻子,1對子,可以
“11223344567” -> “11”+“234”+“234”+“567”, 1對子,3順子,可以
-> “123”+“123”+“44”+“567”, 另一種組合,也可以
輸入描述:
合法C字符串,只包含’1’-‘9’,且已經按從小到大順序排好;字符串長度不超過15。同一個數字最多出現4次,與實際相符。
輸出描述:
C字符串,“yes"或者"no”
示例1
輸入
2244
輸出no
算法:深搜(dfs),我們只需要在每次判斷時去掉順子或者刻子,不斷搜索下去。我們關注的是搜索的出口,也就是麻將的長度(小於2不能和牌,等於2需判斷是否為對子)即可
#include<string> #include<algorithm> #include<iostream> using namespace std; bool dfs(const string& s){ if(s.size()<2)return false; if(s.size()==2)return s[0]==s[1]; bool flag=false; auto beg=s.begin(),ed=s.end(); while(ed-beg>2){ if(*beg==*(beg+1)&&*beg==*(beg+2)){ string tmp1(s.begin(),beg); string tmp2(beg+3,ed); flag|=dfs(tmp1+tmp2); } else if(*beg+1==*(beg+1)){ int cnt=0; char tmp=*(beg+1); auto it=beg+1; while(*it==tmp){ cnt++; if(++it==ed){ cnt=-1; break; } } if(cnt>0&&tmp+1==*it){ string tmp1(s.begin(),beg); string tmp2; tmp2.insert(0,cnt-1,tmp); string tmp3(it+1,ed); flag|=dfs(tmp1+tmp2+tmp3); } } ++beg; } return flag; } int main(void){ string s; cin>>s; sort(s.begin(),s.end()); cout<<(dfs(s)?"yes":"no")<<endl; return 0; }