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;
}
HDU 4431 Mahjong (DFS,暴力枚举,剪枝)的更多相关文章
- HDU - 4431 Mahjong (模拟+搜索+哈希+中途相遇)
题目链接 基本思路:最理想的方法是预处理处所有胡牌的状态的哈希值,然后对于每组输入,枚举每种新加入的牌,然后用哈希检验是否满足胡牌的条件.然而不幸的是,由于胡牌的状态数过多(4个眼+一对将),预处理的 ...
- HDU 5778 abs (暴力枚举)
abs Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Problem De ...
- HDU 1015.Safecracker【暴力枚举】【8月17】
Safecracker Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is lo ...
- HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)
Problem Description Japanese Mahjong is a four-player game. The game needs four people to sit around ...
- HDU 4431 Mahjong 模拟
http://acm.hdu.edu.cn/showproblem.php?pid=4431 不能说是水题了,具体实现还是很恶心的...几乎优化到哭但是DFS(还加了几个剪枝)还是不行...搜索一直T ...
- HDU - 5128The E-pang Palace+暴力枚举,计算几何
第一次写计算几何,ac,感动. 不过感觉自己的代码还可以美化一下. 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5128 题意: 在一个坐标系中,有n个 ...
- HDU 4431 Mahjong(模拟题)
题目链接 写了俩小时+把....有一种情况写的时候漏了...代码还算清晰把,想了很久才开写的. #include <cstdio> #include <cstring> #in ...
- 【poj 3080】Blue Jeans(字符串--KMP+暴力枚举+剪枝)
题意:求n个串的字典序最小的最长公共子串. 解法:枚举第一个串的子串,与剩下的n-1个串KMP匹配,判断是否有这样的公共子串.从大长度开始枚举,找到了就break挺快的.而且KMP的作用就是匹配子串, ...
- HDU 5339 Untitled (暴力枚举)
题意:给定一个序列,要求从这个序列中挑出k个数字,使得n%a1%a2%a3....=0(顺序随你意).求k的最小值. 思路:排个序,从大的数开始模起,这是因为小的模完还能模大的么? 每个元素可以选,也 ...
随机推荐
- UVa 557 (概率 递推) Burger
题意: 有两种汉堡给2n个孩子吃,每个孩子在吃之前要抛硬币决定吃哪一种汉堡.如果只剩一种汉堡,就不用抛硬币了. 求最后两个孩子吃到同一种汉堡的概率. 分析: 可以从反面思考,求最后两个孩子吃到不同汉堡 ...
- Android平台调用WebService详解
上篇文章已经对Web Service及其相关知识进行了介绍(Android开发之WebService介绍 ),相信有的朋友已经忍耐不住想试试在Android应用中调用Web Service.本文将通过 ...
- C# winform 窗体从右下角向上弹出窗口效果
参考自 http://blog.csdn.net/yilan8002/article/details/7197981 /// <summary> /// 窗体动画函数 注意:要引用Syst ...
- 图解VS2010打包全过程
原文转自:http://blog.csdn.net/shan9liang/article/details/6957308 最近刚刚打包发布了用VS2010开发的一个收费系统,借此讲一讲打包过程,供大家 ...
- 一天一个Java基础——排序
插入排序 直接插入排序: 当插入第i个数据元素k时,由前i-1个数据元素组成已排序的数据序列,将k与数据序列中各数据元素依次进行比较后,插入到数据序列的适当位置,使得插入后的数据序列仍是排序的. 直接 ...
- Delphi 自带的那个 Hand 光标很难看?没关系,一行代码解决问题:
Delphi 自带的那个 Hand 光标很难看?没关系,一行代码解决问题: Screen.Cursors[crHandPoint] := LoadCursor(0, IDC_HAND);放在主窗体 O ...
- 再一次见证mssql中in 与exist的区别
见下面代码 /*+' select * from '+@strDBName +'.dbo.m_aic where nodeid not in(select nodeid from @tmpAIC) ' ...
- 关于join算法的四篇文章
MySQL Join算法与调优白皮书(一) MySQL Join算法与调优白皮书(二) MySQL Join算法与调优白皮书(三) MySQL Join算法与调优白皮书(四) MariaDB Join ...
- Python easy_install
系统中有高版本的Python, 直接pip3 install ipcalc安装,都是装到高版本的Python 系统默认的Python是2.7.6,现在想装到默认版本中,可以使用easy_install ...
- POJ 1077 Eight
题意:经典的八数码=3= 3*3的格子,里面有1~8这8个数字,还有一个空格x,移动空格的位置,直到移到1~8按顺序排好,输出移动的序列. 解法:看到题果断写了个广搜……然后T了……百度了一下说广搜虽 ...