清一色胡牌问题
题目描述:
清一色是麻将番种之一,指由一种花色的序数牌组成的和牌.
数字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; }