【原题】

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】

  1. #include<cstdio>
  2. #include<set>
  3. using namespace std;
  4. typedef unsigned long long ULL;
  5. set<ULL>S;ULL base[101],a[101],mul=97;
  6. inline ULL calc(int k) {return base[k]*a[k]+base[k+1]*a[k+1]+base[k+2]*a[k+2];}
  7. int Test,i;
  8. inline bool dfs(int k,bool two)
  9. {
  10. ULL t=calc(k);
  11. if (S.find(t)!=S.end())
  12. return 0;
  13. S.insert(t);
  14. while (!a[k]) k++;
  15. if (k==101) return two;
  16. if (a[k]&&a[k+1]&&a[k+2])
  17. {
  18. a[k]--;a[k+1]--;a[k+2]--;
  19. if (dfs(k,two)) return 1;
  20. a[k]++;a[k+1]++;a[k+2]++;
  21. }
  22. if (a[k]>=4)
  23. {
  24. a[k]-=4;if (dfs(k,two)) return 1;a[k]+=4;
  25. }
  26. if (a[k]>=3)
  27. {
  28. a[k]-=3;if (dfs(k,two)) return 1;a[k]+=3;
  29. }
  30. if (a[k]>=2&&!two)
  31. {
  32. a[k]-=2;if (dfs(k,1)) return 1;a[k]+=2;
  33. }
  34. return 0;
  35. }
  36. int main()
  37. {
  38. base[1]=1;for (i=2;i<=100;i++) base[i]=base[i-1]*mul;
  39. scanf("%d",&Test);
  40. while (Test--)
  41. {
  42. for (i=1;i<=100;i++) scanf("%lld",&a[i]);
  43. S.clear();
  44. if (dfs(1,0)) puts("Yes");else puts("No");
  45. }
  46. return 0;
  47. }

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

【代码】

  1. #include<cstdio>
  2. #include<set>
  3. using namespace std;
  4. typedef unsigned long long ULL;
  5. set<ULL>S;ULL base[105],a[105],sum,mul=131ll;
  6. int Test,i;
  7. inline bool dfs(int k,bool two,ULL status)
  8. {
  9. if (S.find(status)!=S.end()) return 0;
  10. S.insert(status);
  11. while (!a[k]&&k<=100) k++;
  12. if (k==101) return two;
  13. if (a[k]&&a[k+1]&&a[k+2]&&k<=98)
  14. {
  15. a[k]--;a[k+1]--;a[k+2]--;
  16. if (dfs(k,two,status-base[k]-base[k+1]-base[k+2])) return 1;
  17. a[k]++;a[k+1]++;a[k+2]++;
  18. }
  19. if (a[k]>=4)
  20. {
  21. a[k]-=4;if (dfs(k,two,status-base[k]*4)) return 1;a[k]+=4;
  22. }
  23. if (a[k]>=3)
  24. {
  25. a[k]-=3;if (dfs(k,two,status-base[k]*3)) return 1;a[k]+=3;
  26. }
  27. if (a[k]>=2&&!two)
  28. {
  29. a[k]-=2;if (dfs(k,1,status-base[k]*2-base[100])) return 1;a[k]+=2;
  30. }
  31. return 0;
  32. }
  33. int main()
  34. {
  35. base[1]=1ll;for (i=2;i<=100;i++) base[i]=base[i-1]*mul;
  36. scanf("%d",&Test);
  37. while (Test--)
  38. {
  39. sum=0;for (i=1;i<=100;i++) scanf("%lld",&a[i]),sum+=base[i]*a[i];
  40. S.clear();
  41. if (dfs(1,0,sum)) puts("Yes");else puts("No");
  42. }
  43. return 0;
  44. }

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. 一键切换皮肤的解决思想及iframe嵌套时寻找下级iframe的方法

    项目中有个一键切换皮肤的功能,感觉还不错,记录下,就是各颜色样式设置起来太复杂了,不知道有没有更简便的方法: 1.切换皮肤结构层 <li title="<s:text name= ...

  2. 编译和使用 MySQL C++ Connector

    记录编译 mysql C and C++ connector 和简单访问数据库. 环境: vs2012,  mysql 5.6.13, 基于x64 0. 软件包 mysql http://dev.my ...

  3. IT运维流程 — ITIL

    导读 在IT运维中,最有名也是最实用的流程就是ITIL.说到这里,我想大家都有过实施ITIL痛苦的经历,一定会有人说:我们没有办法实施ITIL. 问:ITIL是什么? 答:ITIL即IT基础架构库(I ...

  4. Java8新特性之重复注解(repeating annotations)浅析

    Java8新特性之重复注解(repeating annotations)浅析 学习了:https://www.jb51.net/article/50827.htm

  5. Cognos创建Oracle数据源错误以及客户端生成加密信息错误

    报加密错误,先删除 signkeypair csk encrytkeypair三个目录错误一: 创建Oracle数据源错误,在cognos connection中创建oracle的数据源,一直测试不成 ...

  6. uva 213 - Message Decoding (我认为我的方法要比书上少非常多代码,不保证好……)

    #include<stdio.h> #include<math.h> #include<string.h> char s[250]; char a[10][250] ...

  7. 【Javascript Demo】防止按钮在短时间内被多次点击

    如果一个按钮可以在短时间内多次点击,那么有可能会被用户恶意点击,为防止这种情况,可以设定一定时间内只能点击一次,其他时间禁止点击按钮. 1.效果如下:     2.代码如下:   <div> ...

  8. C# 单元测试几个方法的用法

    单元测试的基本方法是调用被测代码的函数,输入函数的参数值,获取返回结果,然后与预期测试结果进行比较,如果相等则认为测试通过,否则认为测试不通过. 1.Assert类的使用 Assert.Inconcl ...

  9. MVC4.0网站发布

    一.VS2010下MVC4.0项目的发布 首先,生成网站发布文件. 第一步,"右击"要发布的MVC4.0项目,选择"发布(B)..."选项,如图: 第二步,在& ...

  10. iOS Strong 和 weak

    iOS 5 中对属性的设置新增了strong 和weak关键字来修饰属性(iOS 5 之前不支持ARC) strong 用来修饰强引用的属性: @property (strong) SomeClass ...