清一色胡牌问题

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

 

posted @ 2019-07-08 19:17  YF-1994  阅读(1972)  评论(0编辑  收藏  举报