2012 Asia Tianjin Regional Contest - Mahjong

  要是noip前做过这种题的话……起码心里还有点地呢……
  然而……
  物是人非了啊……
  不过呢,这题相对于斗地主而言还是简单了很多。开个表,记录出现次数,直接爆搜判断就可以过了。
  

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define cr(x) memset(x , 0 , sizeof x)

inline int rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar() ; int x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

map<string , int> m;

void init() {
    m["1m"]=1;m["2m"]=2;m["3m"]=3;
    m["4m"]=4;m["5m"]=5;m["6m"]=6;
    m["7m"]=7;m["8m"]=8;m["9m"]=9;
    m["1s"]=10;m["2s"]=11;m["3s"]=12;
    m["4s"]=13;m["5s"]=14;m["6s"]=15;
    m["7s"]=16;m["8s"]=17;m["9s"]=18;
    m["1p"]=19;m["2p"]=20;m["3p"]=21;
    m["4p"]=22;m["5p"]=23;m["6p"]=24;
    m["7p"]=25;m["8p"]=26;m["9p"]=27;
    m["1c"]=28;m["2c"]=29;m["3c"]=30;
    m["4c"]=31;m["5c"]=32;m["6c"]=33;
    m["7c"]=34;
}

typedef int arr[35];

arr a , c;
int flag;
vector<int> ans;

void input() {
    rep (i , 1 , 13) {
        char ch[10];
        scanf("%s" , ch);
        a[i] = m[ch];
    }
}

const int c13[] = {1 , 9 , 10 , 18 , 19 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34};

bool judge1() {
    int c1 = 0 , c2 = 0;
    rep (i , 0 , 13) {
        if (c[c13[i]]) c1 ++;
        if (c[c13[i]] > 1) c2 ++;
    }
    return c1 == 13 && c2 == 1;
}

bool judge2() {
    int c1 = 0;
    rep (i , 1 , 34) if (c[i] == 2) c1 ++;
    return c1 == 7;
}

#define inR(i) ((1 <= i && i <= 7) || (10 <= i && i <= 16) || (19 <= i && i <= 25))

void dfs(int tot , int c1 , int c2) {
    if (flag) return;
    if (c1 > 4 || c2 > 1) return;
    if (tot == 14) {
        if (c1 == 4 && c2 == 1) flag = 1;
        return;
    }
    rep (i , 1 , 34) {
        int p = 0;
        if (c[i] >= 3) {
            c[i] -= 3;
            p = 1;
            dfs(tot + 3 , c1 + 1 , c2);
            c[i] += 3;
        }
        if (c[i] >= 2) {
            c[i] -= 2;
            p = 1;
            dfs(tot + 2 , c1 , c2 + 1);
            c[i] += 2;
        }
        if (inR(i) && c[i] && c[i + 1] && c[i + 2]) {
            c[i] -- , c[i + 1] -- , c[i + 2] --;
            p = 1;
            dfs(tot + 3 , c1 + 1 , c2);
            c[i] ++ , c[i + 1] ++ , c[i + 2] ++;
        }
        if (c[i]) return;
    }
}

bool ok() {
    cr(c);
    rep (i , 1 , 14) c[a[i]] ++;
    rep (i , 1 , 14) if (c[a[i]] > 4) return 0;
    if (judge1() || judge2()) return 1;
    flag = 0;
    dfs(0 , 0 , 0);
    return flag;
}

void solve() {
    ans.clear();
    rep (i , 1 , 34) {
        a[14] = i;
        if (ok())
            ans.push_back(i);
    }
    if (ans.empty()) {
        puts("Nooten");
    } else {
        printf("%d" , (int) ans.size());
        rep (i , 0 , ans.size() - 1) {
            for (map<string , int>::iterator it = m.begin();it != m.end();it ++)
                if (it -> second == ans[i])
                    cout << " " <<  it -> first;
        }
        puts("");
    }
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
    #endif
    init();
    per (T , rd() , 1) {
        input();
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值