UVa 11210 Chinese Mahjong (暴力,遞歸尋找)


題意:這個題意。有點麻煩,就是說給定13張牌,讓你求能“聽”的牌。(具體的見原題)

原題鏈接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2151

析:看到這個題,真是麻煩啊,我又不懂麻將,看了好久才明白什么是“聽”。分析一下思路。

首先對所有的牌都進行編號,然后暴力,首先的是先判斷是哪個是將,然后再進一步判斷,

哪一個是刻子,和順子,用遞歸很簡單的,只要全搜一下就好。整體不難,容易理解。

注意的是有的牌已經四張了,就不能再“聽”了,這是一個坑。

代碼如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 15 + 5;
const char *mahjong[] = {
    "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"
};//打個麻將表
int c[35], id[15];
char s[100];

int getid(const char *s){//獲得每張牌的id
    for(int i = 0; i < 34; ++i)
        if(!strcmp(mahjong[i], s))  return i;

    return -1;
}

bool dfs(int d){
    for(int i = 0; i < 34; ++i) if(c[i] > 2){//刻子
        if(3 == d)  return true;//除了將,那么刻子和順子的和應該是4個,所以這就已經判斷安然無恙了
        c[i] -= 3;
        if(dfs(d+1)){  c[i] += 3;  return true; }//找到時,要注意把c[i]改回來
        c[i] += 3;
    }

    for(int i = 0; i < 24; ++i)
        if(i % 9 <= 6 && c[i] > 0 && c[i+1] > 0 && c[i+2] > 0) {//順子
            if(3 == d)  return true;//同上
            --c[i];  --c[i+1];  --c[i+2];
            if(dfs(d+1)){  ++c[i];  ++c[i+1];  ++c[i+2];  return true; }//同上
            ++c[i];  ++c[i+1];  ++c[i+2];
        }

    return false;
}

bool judge(){
    for(int i = 0; i < 34; ++i) if(c[i] > 1){//暴力,一張一張判斷的,是不是將
            c[i] -= 2;//判斷是將了
            if(dfs(0)){ c[i] += 2;  return true; }//成立,要把c[i]改回來
            c[i] += 2;
    }

    return false;//不成立
}

int main(){
//    freopen("in.txt", "r", stdin);
    int kase = 0;
    bool ok;
    while(scanf("%s", s) == 1){
        if('0' == s[0])  break;
        id[0] = getid(s);
        for(int i = 1; i < 13; ++i){
            scanf("%s", s);
            id[i] = getid(s);//獲得id
//            printf("%d %d\n", i, id[i]);
        }
//        printf("\n");
        ok = false;

        memset(c, 0, sizeof(c));//每次要清空
        for(int i = 0; i < 13; ++i)  ++c[id[i]];//獲得每張牌的數量

//        puts("++");
        printf("Case %d:", ++kase);
        for(int i = 0; i < 34; ++i){
            if(c[i] > 3)  continue;//如果這張牌已經四張了,就不能再聽了,是坑

            ++c[i];
            if(judge()){
                ok = true;
                printf(" %s", mahjong[i]);//輸出
            }
            --c[i];
        }

        if(!ok)  printf(" Not ready");
        printf("\n");
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM