UVa 11210打卡

算法竞赛入门经典训练指南打卡

题目链接:UVa 11210

思路

简单的暴力枚举题,我们可以分别尝试添加34张牌中的一张牌,凑成14张牌,查看是否可以和牌
	如果可以和牌,则输出这张牌,如果所有牌加上去都不可以和牌则输出Not ready
判断和牌的方式:枚举+深搜+回溯
		首先枚举将,然后深搜其他的牌是否满足可以组成四组(刻子和顺子),如果可以则说明可以和牌
具体细节看到代码注释

代码如下:

#include <iostream>
#include <vector>
#define ton(i , n) for(int i = 0 ; i < n ; ++ i)

using namespace std ;

const string mahjong[34] = {"1T", "2T", "3T", "4T", "5T", "6T", "7T", "8T", "9T",
                          "1S", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S",
                          "1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W",
                          "DONG", "NAN", "XI", "BEI",
                          "ZHONG", "FA", "BAI"};        //将牌转换成数字,方便存储牌的数量

bool victory(vector<int> number , int d){
    ton(i , 34)
        if(number[i] >= 3){     //可以做成刻子
            if (d == 3)     //组数已经达到3组,加上当前这组刻子刚好四组,可以和牌
                return true ;
            number[i] -= 3 ;        //做一组刻子
            if(victory(number , d + 1))     //上一行代码做成了一组刻子,组数+1,深搜
                return true ;
            number[i] += 3 ;       //这组刻子组成了无法和牌,拿回来
        }
    ton(i , 24)
        if (i % 9 <= 6 && number[i] >= 1 && number[i + 1] >= 1 && number[i + 2] >= 1){  //顺子开头只能是1~7,且这3张牌都有至少一个
            if (d == 3)         //同上。加上当前这组顺子组成4组。和了
                return true ;
            number[i] -- ;
            number[i + 1] -- ;
            number[i + 2] -- ;      //同上,组成顺子
            if(victory(number , d + 1))     //同上,深搜
                return true ;
            number[i] ++ ;
            number[i + 1] ++ ;
            number[i + 2] ++ ;      //同上,拿回来
        }
    return false ;
}

bool check(vector<int> number){
    ton(i , 34)
        if(number[i] >= 2){
            number[i] -= 2 ;        //将当前牌做为将
            if (victory(number , 0))        //查找剩下的牌是否可以组成四组(刻子或者顺子)
                return true ;   //如果可以说明可行
            number[i] += 2 ;    //不可以则将之前去掉的将拿回来
        }
    return false ;      //如果都不行返回false
}


int convert(string temp){
    ton(i , 34)
        if(mahjong[i] == temp)
            return i ;      //找到该牌,返回id
    return -1 ;
}

int main(){
    int k = 1 ;
    bool ans ;
    string temp ;
    while (cin >> temp && temp != "0"){     //如果第一个输入为0则说明输入结束
        vector<int> number(34 , 0) ;        //number用来记录每张牌的数量
        ans = false ;
        number[convert(temp)] ++ ;      //convert找到该牌对应的id,这张牌的数量+1
        ton(i , 12){
            cin >> temp ;
            number[convert(temp)] ++ ;      //输入剩下的十二张牌
        }
        cout << "Case " << k ++ << ":" ;
        ton(i , 34){
            if(number[i] == 4)
                continue ;      //number[i]为4,说明这张牌不可能再出现了
            number[i] ++ ;      //加入一张牌,凑成14张进行判断
            if(check(number)){      //判断加入该牌之后是否可以和牌
                ans = true ;
                cout << " " << mahjong[i] ;     //可以和牌,输出当前听的牌
            }
            number[i] -- ;
        }
        if(!ans)
            cout << " Not ready" ;      //如果无法和牌,输出Not ready
        cout << endl ;
    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/just_gong/article/details/107932562
今日推荐