Uva 11210 Chinese Mahjong

算法比较简单,郁闷的是卡在输出格式上,多了一个换行,在输出时一定要和题目的输出一直,看清题目的要求。

    出现这些问题的本质,还是编程思路不够严谨,要着重锻炼自己思维的严谨性、写代码时的专注度。对于分支部分的代码考虑清楚再敲,复制、排序在重复用到的数组中考虑覆盖、初始化的问题。

    本题是一个简单的搜索。有一点,对按牌大小排过序的数组求顺子,以当前牌为顺子的起始,从左到右匹配顺子,如果未匹配上,则当前排不存在顺子。因为在排序数组中,若果搜索到当前下标,则说明之前的一小于当前下标的牌开始的顺子都匹配失败,也就是说当前下标牌在顺子中排在第2-n个位置的情况都匹配失败,所以若果当前下标匹配失败则当前排肯定无顺子。

    对字符串输入的,开一个str数组,匹配下标,转换成整数操作。方便!

 

思路:从34张牌中取一张加入,看是否胡牌,胡牌则输出。

先选将,搜索顺子和刻子的排列组合,每次搜索到第3层(0开始)时则成功,3*4 +2 == 14;

每一张牌匹配刻子、和以它开头的顺子,匹配成功则返回1,否则返回0;

 

 

 

#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h> 

using namespace std;

const char* mj[] = {
"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 us[34];//1- 9s  1*9+1 - 2*9t, 3*9+1 - 4*9,    


int hand[14],kase = 1;

int check(int dep)
{
    for(int i = 0; i < 14; i++)
    {
        
        if(!us[hand[i]])continue; 
        
        if(us[hand[i]] >= 3)//找当前牌的 刻子 
        {
            //printf("%d\n",dep);
            if(dep == 3)return 1;
            us[hand[i]] -= 3;
            int r = check(dep + 1);
            us[hand[i]] +=3;
            if(r)return 1;
            
        }
        

        // 找当前牌的 顺子 
        if((
            (hand[i] >= 0 && hand[i] < 9 - 2) ||
            (hand[i] >=9  && hand[i] < 18 - 2)|| 
            (hand[i] >=18  && hand[i] < 27 - 2)
            ) &&
             us[hand[i] + 1] > 0 && us[hand[i] + 2] >0)//箭牌 和风牌 没有 顺子 
        {  
                if(dep == 3)return 1;
                us[hand[i]]--;
                us[hand[i] + 1]--;
                us[hand[i] + 2]--;
                int result = check(dep+1);
                us[hand[i]]++;
                us[hand[i] + 1]++;
                us[hand[i] + 2]++;
                return result;
        }
        
        return 0; 
    }
    
}

void find()
{
    int is_ting = 0;
    
    
    int tmp[13];
    for(int i = 0; i < 13; i++)tmp[i] = hand[i];
    for(int i = 0; i < 34; i++)
    {
        if(us[i] == 4)continue;
        
        hand[13] = i;
        us[i]++;
        sort(hand,hand + 14);
      
        for(int j = 0; j < 14; j += us[hand[j]])
        {
            if(us[hand[j]] >= 2) 
            {
                us[hand[j]] -= 2;
                if(check(0))
                {
                   printf(" %s",mj[i]);
                   is_ting = 1; 
                   us[hand[j]] += 2;
                   break;
                }
                us[hand[j]] += 2;
            }
            
        }
        
        
        us[i] --;
        for(int k = 0; k < 13; k++)hand[k] = tmp[k];
    }          
    if(!is_ting)printf(" Not ready");
    printf("\n");
}
 

int getId(const char* c)
{
    for(int i = 0; i < 34; i++)
    if(!strcmp(c,mj[i]))return i;
}

int main(int argc, char *argv[])
{
    char str[5];
    while(1)
    {
        memset(us,0,sizeof(us));
        scanf("%s",str);
        if(str[0] == '0')break;
        hand[0] = getId(str);
        us[hand[0]]++;
        
        for(int i = 1; i < 13; i++)
        {
            scanf("%s",str);
            hand[i] = getId(str);
            us[hand[i]]++;
        }
        printf("Case %d:",kase++);
        find();
        
        
        
        
    }
    
    
    //system("PAUSE");
    return EXIT_SUCCESS;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值