当前位置: 首页 > news >正文

bzoj 1860: [Zjoi2006]Mahjong麻将 题解

【原题】

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

Day2


【分析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;
}

相关文章:

  • git使用点滴:如何查看commit的内容和git 获取最近一次提交的commit id
  • 美光Sun合作长寿命SLC闪存 100万次写入
  • OCZ新Summit系列固态硬盘强悍性能曝光
  • 用MAID 2.0降低存储费用
  • 为什么要创建开放源码的PlayScala社区?
  • 关于 TCP/IP,必知必会的十个问题
  • OSStatus code 查询
  • TCP协议中FLAG的含义
  • TypeScript学习笔记(六):泛型
  • Unity3D之Mecanim动画系统学习笔记(十):Mecanim动画的资源加载相关
  • Android零基础入门第11节:简单几步带你飞,运行Android Studio工程
  • java中你确定用对单例了吗?
  • 深入分析Sleep(0)与Sleep(1)的区别
  • swift3.0常用操作包含删除字符串(string),更换字符串,插入字符串
  • 第21章 RTX 低功耗之睡眠模式
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • Angular4 模板式表单用法以及验证
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • Brief introduction of how to 'Call, Apply and Bind'
  • javascript从右向左截取指定位数字符的3种方法
  • JavaScript异步流程控制的前世今生
  • Java比较器对数组,集合排序
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Quartz初级教程
  • RxJS: 简单入门
  • scala基础语法(二)
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Terraform入门 - 3. 变更基础设施
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue2.0项目引入element-ui
  • 从0实现一个tiny react(三)生命周期
  • 大数据与云计算学习:数据分析(二)
  • 当SetTimeout遇到了字符串
  • 对超线程几个不同角度的解释
  • 高性能JavaScript阅读简记(三)
  • 好的网址,关于.net 4.0 ,vs 2010
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 入口文件开始,分析Vue源码实现
  • 使用权重正则化较少模型过拟合
  • 手机端车牌号码键盘的vue组件
  • 学习Vue.js的五个小例子
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 如何正确理解,内页权重高于首页?
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $$$$GB2312-80区位编码表$$$$
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (day6) 319. 灯泡开关
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (六)Hibernate的二级缓存