HDU 4431 Mahjong (DFS,暴力枚举,剪枝)

题意:给定 13 张麻将牌,问你是不是“听”牌,如果是输出“听”哪张。

析:这个题,很明显的暴力,就是在原来的基础上再放上一张牌,看看是不是能胡,想法很简单,也比较好实现,结果就是TLE,一直TLE,这不科学啊。。。

好不容易写出来的,竟然TLE。。。心痛。就是先确定一个将牌,然后再对刻子和顺子进行分析,其实是要剪枝的,就是在如果有1张或者两张牌,而你又不能构成刻子的时候,就要返回false,因为这就已经没解了。

这一个剪枝,就AC了。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <stack>
using namespace std ;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 10 + 5;
const int mod = 1e9 + 7;
const char *mark = "+-*";
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
int n, m;
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
const char* mahjong[] = {
    "1m", "2m", "3m", "4m", "5m", "6m", "7m", "8m", "9m",
    "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
    "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p",
    "1c", "2c", "3c", "4c",
    "5c", "6c", "7c"
};
map<string, int> mp;
inline void init(){
    for(int i = 0; i < 34; ++i)
        mp[string(mahjong[i])] = i;
}
int c[35];

bool dfs(int d){
    for(int i = 0; i < 34; ++i){
        int cnt = 0;
        if(c[i] >= 3){
        if(d == 3) return true;
        ++cnt;
        c[i] -= 3;
        if(dfs(d+1)){ c[i] += 3;  return true; }
        c[i] += 3;
        }

        if(i <= 24 && i % 9 <= 6 && c[i] >= 1 && c[i+1] >= 1 && c[i+2] >= 1){
            ++cnt;
            if(d == 3)   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];
        }
        if(cnt == 0 && c[i])  return false; //这种牌有但是不符合顺子或者刻子结束这层搜索
        if(c[i])  break; //这里剪枝是因为上面的搜索下次遍历的时候还会继续从他这遍历,所以就不用继续下去了
    }
    return false;
}

inline bool check(){
    for(int i = 0; i < 34; ++i){
        if(c[i] >= 2){
            c[i] -= 2;
            if(dfs(0)){ c[i] += 2;   return true; }
            c[i] += 2;
        }
    }
    return false;
}
int ans[50];

inline bool solvefood(){
    int food[35];
    memcpy(food, c, sizeof(c));
    int cnt = 0;
    for(int i = 0; i < 20; i += 9){
        --food[i], cnt += food[i];
        if(food[i] < 0) return false;
    }
    for(int i = 8; i < 30; i += 9){
        --food[i], cnt += food[i];
        if(food[i] < 0) return false;
    }
    for(int i = 27; i < 34; ++i){
        --food[i], cnt += food[i];
        if(food[i] < 0)  return false;
    }
    return cnt == 1;
}

inline bool solveseven(){
    for(int i = 0; i < 34; ++i)
        if(c[i] != 2 && c[i] != 0)  return false;
    return true;
}

int main(){
    char s[10];
    init();
    int T;  scanf("%d", &T);
    while(T--){
        memset(c, 0, sizeof(c));
        for(int i = 0; i < 13; ++i){
            scanf("%s", s);
            ++c[mp[string(s)]];
        }

        int cnt = 0;
        for(int i = 0; i < 34; ++i){
            if(c[i] >= 4)  continue;
            ++c[i];
            if(solvefood()) ans[cnt++] = i;
            else if(solveseven())  ans[cnt++] = i;
            else if(check())  ans[cnt++] = i;
            --c[i];
        }

        if(!cnt)  puts("Nooten");
        else{
            printf("%d", cnt);
            for(int i = 0; i < cnt; ++i)
                printf(" %s", mahjong[ans[i]]);
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-10-25 04:54:04

HDU 4431 Mahjong (DFS,暴力枚举,剪枝)的相关文章

hdu4277USACO ORZ dfs暴力枚举+map

//给N个 问rails用着N个rails能构成几个不同的三角形 //dfs暴力枚举+(map) #include<cstdio> #include<cstring> #include<map> #include<iostream> using namespace std ; int ans ; int a[20] ; int n ; int sum = 0 ; struct node { int a , b , c ; bool operator == (

HDU - 4431 Mahjong (模拟+搜索+哈希+中途相遇)

题目链接 基本思路:最理想的方法是预处理处所有胡牌的状态的哈希值,然后对于每组输入,枚举每种新加入的牌,然后用哈希检验是否满足胡牌的条件.然而不幸的是,由于胡牌的状态数过多(4个眼+一对将),预处理的复杂度太高($O(34^5)$),因此需要想办法优化一下. 我们可以预处理出所有“加上一对将之后可以胡牌”的状态,这样预处理的复杂度就成了$O(34^4)$,在可接受的范围内了.在检验的时候,只需要枚举去掉哪一对将,就可以$O(1)$检验是否能胡牌了(有种中途相遇的感觉),另外两种特殊情况单独判断即

HDU 5778 abs (暴力枚举)

abs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 399    Accepted Submission(s): 140 Problem Description Given a number x, ask positive integer y≥2, that satisfy the following conditions:1.

HDU 5778 abs(暴力枚举)——BestCoder Round #85 1003

传送门 abs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1474    Accepted Submission(s): 511 Problem Description Given a number x, ask positive integer y≥2, that satisfy the following condition

HDU 1015.Safecracker【暴力枚举】【8月17】

Safecracker Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Klein safe behind a painting in the second-floor library. Klein safes are extremely rare; most of them, along with Klein and his factory, were des

HDU 4431 Mahjong (麻将、神坑模拟题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4431 题面: Mahjong Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4219    Accepted Submission(s): 842 Problem Description Japanese Mahjong is a fou

ZOJ 3816 Generalized Palindromic Number dfs+暴力枚举

题目链接:点击打开链接 题意: 给定一个数n 找一个最大的数u使得u<n && u为回文. 枚举前面有多少位是一样的.然后分类讨论.啪啦啪啦 #include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <vector> using namespace std; typedef long long ll; cons

HDU - 5128The E-pang Palace+暴力枚举,计算几何

第一次写计算几何,ac,感动. 不过感觉自己的代码还可以美化一下. 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5128 题意: 在一个坐标系中,有n个点,从中找到两个互不touch,互不cross的两个矩形(边要和坐标轴平行),使得面积最大. 思路: 枚举每个点,n的四次方,这题有个坑点是“回型矩阵”,是真的坑,然后discuss区里说的十字形矩阵是骗人的. 每次对枚举的四个点进行check,如果两个矩阵的四个点相互不在对方的矩阵中,那么这组就是

Network Saboteur (DFS暴力枚举)

A university network is composed of N computers. System administrators gathered information on the traffic between nodes, and carefully divided the network into two subnetworks in order to minimize traffic between parts. A disgruntled computer scienc