枚举+搜索 hdu-4431-Mahjong
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4431
题目大意:
给一副牌,求出所有能糊的牌。
解题思路:
枚举每一张牌,看能不能糊。
因为一共只有14张牌,每次依据将,去掉三张牌,判断最后两张牌是否一样。
七对和十三幺单独考虑,
注意:
1、1p 1p 1s 9s 1m 9m 1c 2c 3c 4c 5c 6c 7c 这样的也可以糊9p。
2、七对时,要为不同的牌,1s 1s 1s 1s 不能糊七对。
剪枝:
1、对于不是c色牌,能糊的牌一定出现在手牌或+1,-1同色牌中,所以只用枚举这些可以糊的牌即可。
2、对于单独的一张牌,左右相邻没有同色牌时,不能糊。
贴几组测试数据:
20
1p 2p 3p 7p 8p 9p 1s 2s 3s 1c 1c 2c 2c
2 1c 2c
1p 2p 3p 3p 3p 3p 4p 5p 1m 2m 3m 4m 5m
2 3m 6m
1s 2s 3s 2c 2c 2c 2p 3p 5m 6m 7m 1p 1p
2 1p 4p
1p 1p 2p 3p 4s 5s 6s 7c 7c 3s 3s 2m 2m
Nooten
1p 1p 1p 2p 2p 3p 3p 4p 4p 5p 6p 7p 8p
6 2p 3p 5p 6p 8p 9p
1p 2p 3p 3p 3p 4p 5p 1m 2m 3m 4m 5m 6m
2 3p 6p
1p 2p 3p 3p 3p 3p 4p 5p 1m 2m 3m 4m 5m
2 3m 6m
1p 2p 3p 3p 3p 3p 4p 5p 6p 1m 2m 3m 4m
2 1m 4m
1c 2c 3c 4c 5c 6c 7c 1p 9p 1m 9m 1s 9s
13 1m 9m 1s 9s 1p 9p 1c 2c 3c 4c 5c 6c 7c
1p 1p 3p 2p 5p 2p 6p 7p 3p 4p 5p 6p 4p
3 1p 4p 7p
1p 1p 2p 3p 2p 3p 4p 4p 5p 5p 6p 7p 7p
2 3p 6p
1p 1p 9p 9p 1m 1m 9m 9m 1s 9s 1s 9s 7c
1 7c
1p 1p 1p 1p 1m 1m 1m 1s 9s 1c 1c 1s 9s
Nooten
1p 1p 1s 9s 1m 9m 1c 2c 3c 4c 5c 6c 7c
1 9p
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; /*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
map<char,int>myp;
int save[5][15],cnt;
char sa[5];
char pp[4]={'m','s','p','c'};
bool flag,ans[40],hav[40]; void juqi(int a) //判断是否是七对
{
for(int i=0;i<34;i++)
{
int x=i/9,y=i%9;
if(!save[x][y])
continue;
if(save[x][y]!=2)
return ;
}
//printf("qidui yes\n");
++cnt,ans[a]=true;
return ;
}
void jushi(int a) //判断是否是十三幺
{
for(int i=0;i<3;i++)
{
if(save[i][0]!=1&&save[i][0]!=2)
return ;
if(save[i][8]!=1&&save[i][8]!=2)
return ;
for(int j=1;j<8;j++)
if(save[i][j])
return ;
}
for(int i=0;i<7;i++)
if(save[3][i]!=1&&save[3][i]!=2)
return ;
++cnt,ans[a]=true;
return ;
}
void dfs(int num,int val)
{
if(flag)
return ;
if(num==2)
{
for(int i=0;i<4;i++)
{
for(int j=0;j<=((i==3)?6:8);j++)
if(save[i][j]==2) //最后两张牌,肯定是一样的才可能糊
{
flag=true;
if(!ans[val])
++cnt,ans[val]=true;
return ;
}
else if(save[i][j])
return ;
}
}
for(int i=0;i<4;i++)
{
for(int j=0;j<(i==3?7:9);j++)
{
if(save[i][j]>=3) //三张一样的牌
{
save[i][j]-=3;
dfs(num-3,val);
save[i][j]+=3;
if(flag)
return ;
}
if(!j||j==8||i==3)
continue;
if(save[i][j]&&save[i][j-1]&&save[i][j+1])//连续三张同色牌,注意c牌不行
{
save[i][j]--,save[i][j-1]--,save[i][j+1]--;
dfs(num-3,val);
save[i][j]++,save[i][j-1]++,save[i][j+1]++;
if(flag)
return ;
}
}
}
}
bool iscan()
{
for(int i=0;i<3;i++)
{
if(save[i][0]==1&&save[i][1]==0)
return false;
int j;
for(j=1;j<=7;j++) //当为只有1张牌,且左右没牌
{
if(save[i][j]==1&&save[i][j-1]==0&&save[i][j+1]==0)
return false;
}
if(save[i][j]==1&&save[i][j-1]==0)
return false;
}
for(int i=0;i<7;i++)
if(save[3][i]==1)
return false;
return true;
}
int main()
{
myp['m']=0,myp['s']=1,myp['p']=2,myp['c']=3;
int t; scanf("%d",&t);
while(t--)
{
memset(save,0,sizeof(save));
memset(ans,false,sizeof(ans));
memset(hav,false,sizeof(hav));
for(int i=1;i<=13;i++)
{
scanf("%s",sa);
save[myp[sa[1]]][*sa-'0'-1]++;
int xx=myp[sa[1]]*9+*sa-'0'-1;
hav[xx]=true; //hav为能够糊的牌
if(xx%9) //当然c牌有些不能糊也算进去了,不要紧
{
if(xx%9==8)
hav[xx-1]=true;
else
hav[xx-1]=hav[xx+1]=true;
}
else
hav[xx+1]=true;
}
cnt=0;
for(int i=0;i<34;i++)
{
if(save[i/9][i%9]>=4) //这张牌已经没有了
continue;
save[i/9][i%9]++;
jushi(i);
if(!hav[i]||!iscan()) //两个剪枝
{
save[i/9][i%9]--;
continue;
}
juqi(i);
flag=false;
dfs(14,i);
save[i/9][i%9]--;
}
if(!cnt)
{
printf("Nooten\n");
continue;
}
printf("%d",cnt);
for(int i=0;i<34;i++)
{
if(ans[i])
printf(" %d%c",i%9+1,pp[i/9]);
}
putchar('\n');
}
return 0;
}
枚举+搜索 hdu-4431-Mahjong的更多相关文章
- HDU 4431 Mahjong (DFS,暴力枚举,剪枝)
题意:给定 13 张麻将牌,问你是不是“听”牌,如果是输出“听”哪张. 析:这个题,很明显的暴力,就是在原来的基础上再放上一张牌,看看是不是能胡,想法很简单,也比较好实现,结果就是TLE,一直TLE, ...
- 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 (模拟+搜索+哈希+中途相遇)
题目链接 基本思路:最理想的方法是预处理处所有胡牌的状态的哈希值,然后对于每组输入,枚举每种新加入的牌,然后用哈希检验是否满足胡牌的条件.然而不幸的是,由于胡牌的状态数过多(4个眼+一对将),预处理的 ...
- HDU 4431 Mahjong 模拟
http://acm.hdu.edu.cn/showproblem.php?pid=4431 不能说是水题了,具体实现还是很恶心的...几乎优化到哭但是DFS(还加了几个剪枝)还是不行...搜索一直T ...
- HDU 4431 Mahjong(模拟题)
题目链接 写了俩小时+把....有一种情况写的时候漏了...代码还算清晰把,想了很久才开写的. #include <cstdio> #include <cstring> #in ...
- hdu4431 Mahjong 枚举搜索。。
japanese麻将什么玩意..都没有豪华七对... 没什么难的 就是枚举搜索了 分三种类型的胡牌 f1是七对 f2是十三幺 f3是普通的胡牌 就先找一对 再找三个三个的 就是一直超时..在峰峰的指导 ...
- Hdu 5379 Mahjong tree (dfs + 组合数)
题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...
- HDU 4900 NO ACM NO LIFE(概率+枚举+搜索)(2014 Multi-University Training Contest 4)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4900 Problem Description There is an old country and ...
- hdu 4431 第37届ACM/ICPC 天津赛区现场赛A题 枚举
题意:就是给了13张牌.问增加哪些牌可以胡牌.m是数字,s是条,p是筒,c是数字 胡牌有以下几种情况: 1.一个对子 + 4组 3个相同的牌或者顺子. 只有m.s.p是可以构成顺子的.东西南北这样 ...
- HDU 5379——Mahjong tree——————【搜索】
Mahjong tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
随机推荐
- Python学习之collections module-defaultdict()
defaultdict()继承自dict系统内置类型defaultdict()定义以及作用: 返回一个和dictionay类似对象,和dict不同: 1. 可以制定key对应value ...
- 转:requirejs打包压缩r.js使用示例
为了应对日益复杂,大规模的JavaScript开发.我们化整为零,化繁为简.将复杂的逻辑划分一个个小单元,各个击破.这时一个项目可能会有几十个甚至上百个JS文件,每个文件为一个模块单元.如果上线时都是 ...
- 浏览器对body节点scrollTop解析的差异
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style t ...
- perl学习(5) 输入和输出
1.1. 从标准输入设备输入 <STDIN> 行输入操作在到达文件的结尾时将返回undef,在while循环的条件中不能使用chomp: while (defined($line = &l ...
- C# 计算器 如果设置键盘输入的监听事件
这个事情困扰了我好久,之前java写的计算器程序可以正常运行了,但是因为打包问题(尝试过多次,感觉好麻烦,个人比较崇尚“点子”,注重创新,思来想去之后,决定试试C#模仿java再写一遍),想要用C#模 ...
- Linux下的定时器
以下摘自linux下的man文件:(man getitimer) #include <sys/time.h> int getitimer(int which, struct iti ...
- iOS Responder Chain 响应者链
一.事件分类 对于IOS设备用户来说,他们操作设备的方式主要有三种:触摸屏幕.晃动设备.通过遥控设施控制设备.对应的事件类型有以下三种: 1.触屏事件(Touch Event) 2.运动事件(Moti ...
- 小猪猪C++笔记基础篇(六)参数传递、函数重载、函数指针、调试帮助
小猪猪C++笔记基础篇(六) ————参数传递.函数重载.函数指针.调试帮助 关键词:参数传递.函数重载.函数指针.调试帮助 因为一些事情以及自己的懒惰,大概有一个星期没有继续读书了,已经不行了,赶紧 ...
- java多线程监听JMS、MQ队列
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可. 转载请注明出处和作者.http://blog.csdn.net/xtj332 背景:消息队列中有非常多的消息需要 ...
- c语言中malloc realloc 和calloc的联系与区别
(1)C语言跟内存分配方式 <1>从静态存储区域分配. 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量.static变量.<2> ...