【原题】

1860: [Zjoi2006]Mahjong麻将

Time Limit: 1 Sec  Memory Limit: 64 MB

Submit: 211  Solved: 122

[Submit][Status]

Description

Input

第一行一个整数N(N<=100),表示玩了N次超级麻将。 接下来N行。每行100个数a1..a100,描写叙述每次玩牌手中各种牌的数量。ai表示数字为i的牌有ai张。(0<=ai<=100)

Output

输出N行,若胡了则输出Yes,否则输出No,注意区分Yes。No的大写和小写!

Sample Input

3

2 4 0 0 0 0 0 …… 0(一共98个0)

2 4 2 0 0 0 0 …… 0(一共97个0)

2 3 2 0 0 0 0 …… 0(一共97个0)

Sample Output

Yes

Yes

No

HINT

Source

【分析1】原来记得也有一道麻将的判和问题(当然不是国家集训队的那道)。

当时随便用贪心使过去了。可是这里3张牌和4张牌结合在了一起,于是贪心肯定挂了。然后就百思不得其解。

瞄了一眼题解:原来是爆搜。然后開始自己YY。由于最多是三张连续的牌,所以假设1--K-1张牌都没了,第K张牌一定仅仅会影响到K+1和K+2。

然后我就把K去爆搜。

显然光是这样肯定T了。

假设我把1--K-1以多种方法所有消掉了,第K种的状态就仅仅需搜一遍就可以。因此我依据K,K+1,K+2眼下的数量以及K的位置HASH一下。

PS:用了凌神的64位自然溢出。

【代码1】

#include<cstdio>
#include<set>
using namespace std;
typedef unsigned long long ULL;
set<ULL>S;ULL base[101],a[101],mul=97;
inline ULL calc(int k) {return base[k]*a[k]+base[k+1]*a[k+1]+base[k+2]*a[k+2];}
int Test,i;
inline bool dfs(int k,bool two)
{
ULL t=calc(k);
if (S.find(t)!=S.end())
return 0;
S.insert(t);
while (!a[k]) k++;
if (k==101) return two;
if (a[k]&&a[k+1]&&a[k+2])
{
a[k]--;a[k+1]--;a[k+2]--;
if (dfs(k,two)) return 1;
a[k]++;a[k+1]++;a[k+2]++;
}
if (a[k]>=4)
{
a[k]-=4;if (dfs(k,two)) return 1;a[k]+=4;
}
if (a[k]>=3)
{
a[k]-=3;if (dfs(k,two)) return 1;a[k]+=3;
}
if (a[k]>=2&&!two)
{
a[k]-=2;if (dfs(k,1)) return 1;a[k]+=2;
}
return 0;
}
int main()
{
base[1]=1;for (i=2;i<=100;i++) base[i]=base[i-1]*mul;
scanf("%d",&Test);
while (Test--)
{
for (i=1;i<=100;i++) scanf("%lld",&a[i]);
S.clear();
if (dfs(1,0)) puts("Yes");else puts("No");
}
return 0;
}

【分析2】上述做法尽管例子过了。可是狂WA不止。后来发现这种状态数太多了,HASH肯定会被卡掉。在WCY大神的指导下。我发现仅仅需把K+1~N的情况哈希一下,这样子状态数显然变小了。

【代码】

#include<cstdio>
#include<set>
using namespace std;
typedef unsigned long long ULL;
set<ULL>S;ULL base[105],a[105],sum,mul=131ll;
int Test,i;
inline bool dfs(int k,bool two,ULL status)
{
if (S.find(status)!=S.end()) return 0;
S.insert(status);
while (!a[k]&&k<=100) k++;
if (k==101) return two;
if (a[k]&&a[k+1]&&a[k+2]&&k<=98)
{
a[k]--;a[k+1]--;a[k+2]--;
if (dfs(k,two,status-base[k]-base[k+1]-base[k+2])) return 1;
a[k]++;a[k+1]++;a[k+2]++;
}
if (a[k]>=4)
{
a[k]-=4;if (dfs(k,two,status-base[k]*4)) return 1;a[k]+=4;
}
if (a[k]>=3)
{
a[k]-=3;if (dfs(k,two,status-base[k]*3)) return 1;a[k]+=3;
}
if (a[k]>=2&&!two)
{
a[k]-=2;if (dfs(k,1,status-base[k]*2-base[100])) return 1;a[k]+=2;
}
return 0;
}
int main()
{
base[1]=1ll;for (i=2;i<=100;i++) base[i]=base[i-1]*mul;
scanf("%d",&Test);
while (Test--)
{
sum=0;for (i=1;i<=100;i++) scanf("%lld",&a[i]),sum+=base[i]*a[i];
S.clear();
if (dfs(1,0,sum)) puts("Yes");else puts("No");
}
return 0;
}

bzoj 1860: [Zjoi2006]Mahjong麻将 题解的更多相关文章

  1. [BZOJ1860][ZJOI2006]Mahjong(DP)

    1860: [Zjoi2006]Mahjong麻将 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 412  Solved: 248[Submit][Sta ...

  2. BZOJ 4033: [HAOI2015]树上染色题解

    BZOJ 4033: [HAOI2015]树上染色题解(树形dp) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327400 原题地址: BZOJ 403 ...

  3. BZOJ 1861: [Zjoi2006]Book 书架 splay

    1861: [Zjoi2006]Book 书架 Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书 ...

  4. 【DP/二分】BZOJ 1863:[Zjoi2006]trouble 皇帝的烦恼

    863: [Zjoi2006]trouble 皇帝的烦恼 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 465  Solved: 240[Submit][ ...

  5. BZOJ 1003 [ZJOI2006]物流运输trans

    1003: [ZJOI2006]物流运输trans Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4242  Solved: 1765[Submit] ...

  6. [ZJOI2006]超级麻将

    题目描述 很多人都知道玩麻将,当然也有人不知道,呵呵,不要紧,我在这里简要地介绍一下麻将规则: 普通麻将有砣.索.万三种类型的牌,每种牌有1~9个数字,其中相同的牌每个有四张,例如1砣~9砣,1索~9 ...

  7. bzoj 1003 [ZJOI2006]物流运输(最短路+dp)

    [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8973  Solved: 3839[Submit][Status][Di ...

  8. BZOJ 1003[ZJOI2006]物流运输(SPFA+DP)

    Problem 1003. -- [ZJOI2006]物流运输 1003: [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: ...

  9. BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]

    1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][ ...

随机推荐

  1. Java基础(五):数组和Java方法

    一.Java数组: 1.声明数组变量: 首先必须声明数组变量,才能在程序中使用数组.下面是声明数组变量的语法:注意: 建议使用 dataType[] arrayRefVar 的声明风格声明数组变量. ...

  2. URAL 1698

    题目大意:统计位数不大于n的自守数的个数. KB     64bit IO Format:%I64d & %I64u 数据规模:1<=n<=2000. 理论基础: 自守数:参见链接 ...

  3. 笔记本wifi热点设置好后,手机连上但不能上网问题

    这个问题我遇到过,我的原因是因为电脑上装有安全防护软件360的原因 解决方法是:打开360-->找到功能大全中的流量防火墙-->打开局域网防护-->关闭局域网隐身功能,立刻解决了这个 ...

  4. Python开发接水果小游戏

    我研发的Python游戏引擎Pylash已经更新到1.4了.如今我们就来使用它完毕一个极其简单的小游戏:接水果. 下面是游戏截图: 游戏操作说明:点击屏幕左右两边或者使用键盘方向键控制人物移动.使人物 ...

  5. 开源 免费 java CMS - FreeCMS1.9 会员权限管理

    项目地址:http://www.freeteam.cn/ 会员权限管理 管理会员可使用的权限.会员在使用某一特定功能时,如投稿.可依据此会员所在会员组是否有投稿权限来决定会员能否够使用投稿功能. 1. ...

  6. Opera Unite如何架设自己的网站

    1使用Opera的File Sharing可以共享你的文件 2使用Opera的Stream media可以共享你的视频,有些格式甚至可以直接在浏览器端打开(比如MOV,但是需要安装Quicktime的 ...

  7. ZH奶酪:Ubuntu客户端通过SSH方式远程登录Ubuntu服务器

    1.概述 传统的远程登录(telnet,rlogin)时不安全的,他们在网络上用明文传输口令和数据,SSH则是安全的,openssh提供两种级别的验证方式. (1)基于口令的安全验证:知道服务器的帐号 ...

  8. Java从零开始学三十二(正则表达式)

    一.为什么要有正则 正则表达式可以方便的对数据进行匹配,可以执行更加复杂的字符串验证.拆份.替换功能. 例如:现在要求判断一个字符串是否由数字组成,则可以有以下的两种做法: 不使用正则完成 使用正则完 ...

  9. Java从零开始学十二(构造方法)

    一.构造方法 构造方法的主要目的是为类中的属性初始化 二.构造方法的定义格式 class 类名称{ 访问权限 类名称(类型1 参数1,类型2 参数2,…){ 程序语句 ; …    // 构造方法没有 ...

  10. OpenCV 视频处理框架

    OpenCV 本身集成了 FFmpeg,因此对于视频是有解码和编码功能的.尽管其效率在本人看来还不能跟未被封装的FFmpeg相提并论,然用其来对视频进行解码得到图像,然后对图像进行处理并将得到的图像又 ...