码迷,mamicode.com
首页 > 其他好文 > 详细

UVA-11210-Chinese Mahjong

时间:2015-02-26 16:40:46      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:

训练指南24页的题 真是醉了 以为死循环了 原来是循环套的太多了 出一组样例 500S+ 递归尽量减少嵌套循环 会死 我的复杂度34*14*13*12*11*10*9*8*7*6*5*4*3*2*1 提前脑子不好用啊!!!
特别注意以后回溯千万别忘记调用函数后还要把变量改回来

#include<stdio.h>
#include<iostream>
#include<vector>
#include<set>
#include<string>
using namespace std;
vector<int> have;
set<int> ans;
int ji = 0,kase = 0;
bool zuhe(vector<int> now)
{
    int flagzong = 0;
    for(int i = 0; i < now.size(); i++)
        if(now[i] != 99)
        {
            flagzong = 1;
            break;
        }
    if(!flagzong) return true;  //终于完事了
    for(int i = 0; i < now.size(); i++)
        for(int j = 0; j < now.size(); j++)
            for(int k = 0; k < now.size(); k++)
            {
                if(i == j || i == k || j == k || now[i] == 99 || now[j] == 99 || now[k] == 99) continue;
                int a = now[i],b = now[j],c = now[k];
                int flag = 0;
                if(a == b && a == c)    //刻子
                {
                    vector<int> now1(now);
                    now1[i] =99;
                    now1[j] =99;
                    now1[k] =99;
                    if(zuhe(now1)) return true;
                }
                else
                if((a >= 0 && a <= 8 && b >= 0 && b <= 8 && c >= 0 && c <= 8)||(a >= 9 && a <= 17 && b >= 9 && b <= 17 && c >= 9 && c <= 17)||(a >= 18 && a <= 26 && b >= 18 && b <= 26 && c >= 18 && c <= 26)) //顺子
                {
                    if(a + 1 == b && b + 1 == c) flag = 1;
                    if(a + 1 == c && c + 1 == b) flag = 1;
                    if(b + 1 == a && a + 1 == c) flag = 1;
                    if(b + 1 == c && c + 1 == a) flag = 1;
                    if(c + 1 == a && a + 1 == b) flag = 1;
                    if(c + 1 == b && b + 1 == a) flag = 1;
                    if(flag)
                    {
                        vector<int> now1(now);
                        now1[i] =99;
                        now1[j] =99;
                        now1[k] =99;
                        if(zuhe(now1)) return true;
                    }
                }
            }
    return false;
}
bool ting(vector<int> now)  //选择两个牌做将
{
    for(int i = 0; i < now.size(); i++)
        for(int j = 0; j < now.size(); j++)
        {
            if(i == j || now[i] != now[j]) continue;
            vector<int> temp(now);
            temp[i] = 99;
            temp[j] = 99;
            if(zuhe(temp)) return true;

        }
    return false;
}
void solve()
{
    for(int i = 0; i < 34; i++)
    {
        int countt = 0;
        for(int j = 0; j < have.size(); j++)
            if(have[j] == i) countt++;
        if(countt < 4)
        {
            vector<int> temp(have);
            temp.push_back(i);
            if(ting(temp)) ans.insert(i);
        }
    }

}
void build(string str)
{
    if(str == "DONG") have.push_back(27);
    if(str == "NAN") have.push_back(28);
    if(str == "XI") have.push_back(29);
    if(str == "BEI") have.push_back(30);
    if(str == "ZHONG") have.push_back(31);
    if(str == "FA") have.push_back(32);
    if(str == "BAI") have.push_back(33);
    if(str[1] == ‘T‘) have.push_back(str[0] - ‘0‘ - 1);
    if(str[1] == ‘S‘) have.push_back(str[0] - ‘0‘ + 8);
    if(str[1] == ‘W‘) have.push_back(str[0] - ‘0‘ + 17);
}
void print()
{
    set<int>::iterator it;
    if(ans.empty())
    {
        printf(" Not ready\n");
        return;
    }
    for(it = ans.begin(); it != ans.end(); it++)
    {
        printf(" ");
        if((*it) >= 0 && *it <= 8) printf("%dT",(*it) + 1);
        if((*it) >= 9 && *it <= 17) printf("%dS",(*it) - 8);
        if((*it) >= 18 && *it <=26) printf("%dW",(*it) - 17);
        if((*it) == 27) printf("DONG");
        if((*it) == 28) printf("NAN");
        if((*it) == 29) printf("XI");
        if((*it) == 30) printf("BEI");
        if((*it) == 31) printf("ZHONG");
        if((*it) == 32) printf("FA");
        if((*it) == 33) printf("BAI");
    }
    printf("\n");
    return;
}
int main()
{
    string str;
    while(cin>>str && str != "0")
    {
        build(str);
        ji++;
        if(ji % 13 == 0)
        {
            solve();
            printf("Case %d:",++kase);
            print();
            ji = 0;
            have.clear();
            ans.clear();
        }
    }
    return 0;
}

以下是佳神的代码:

#include<stdio.h>
#include<string.h>
int mj[20], cnt[35];
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 getNum(char *str) { //将牌面转换为编号
    for (int i = 0; i < 34; i++) {
        if (!strcmp(mahjong[i], str)) return i;
    }
}
int check2(int n) {
    for (int i = 0; i < 34; i++) { //刻子
        if (cnt[i] >= 3) {
            if (n == 3) return 1;
            cnt[i] -= 3;
            if (check2(n + 1)) return 1;
            cnt[i] += 3;
        }
    }
    for (int i = 0; i <= 24; i++) { //顺子
        if (i % 9 <= 6 && cnt[i] && cnt[i + 1] && cnt[i + 2]) {
            if (n == 3) return 1;
            cnt[i]--;
            cnt[i + 1]--;
            cnt[i + 2]--;
            if (check2(n + 1)) return 1;
            cnt[i]++;
            cnt[i + 1]++;
            cnt[i + 2]++;
        }
    }
    return 0;
}
int check() {
    for (int i = 0; i < 34; i++) {
        if (cnt[i] >= 2) {//将
            cnt[i] -= 2;
            if (check2(0)) return 1;
            cnt[i] += 2;
        }
    }
    return 0;
}
int main() {
    char str[3];
    int Case = 1;
    while (scanf("%s", str) == 1) {
        if (strcmp(str, "0") == 0) break;
        printf("Case %d:", Case++);
        mj[0] = getNum(str);
        for (int i = 1; i < 13; i++) {
            scanf("%s", str);
            mj[i] = getNum(str);//将牌面转化为编号
        }
        int flag = 0;
        for (int i = 0; i < 34; i++) {//枚举34种可能和的情况
            memset(cnt, 0, sizeof(cnt));
            for (int j = 0; j < 13; j++) {
                cnt[mj[j]]++;//统计每张牌出现次数
            }
            if (cnt[i] >= 4) continue;//已出现四次则不再考虑这张牌
            cnt[i]++;
            if (check()) {
                flag = 1;
                printf(" %s", mahjong[i]);
            }
        }
        if (!flag) printf(" Not ready/n");
        else printf("/n");
    }
    return 0;
}

UVA-11210-Chinese Mahjong

标签:

原文地址:http://blog.csdn.net/glqglqglq2/article/details/43953493

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!