解药or毒药

题目描述

  羽毛笔和im是抽签到同一个考场的,她们突然闻到一阵刺鼻的化学试剂的气味。
  机灵鼠:(头都不抬)你们是考生么?还在门口磨蹭什么?快进来帮我忙!!……怎么还不进来?你们拖赛,拖赛,把你们的青春都拖掉赛……
  im:开…开策了> <
  羽毛笔:哎呀~~机灵鼠大人要我们帮什么忙?^^
  机灵鼠:你们看这里的这些药,都是我研制的对付各种症状的解药。可是我一个不小心,每种药都小小地配错了一点原料,所以这些药都有可能在治愈某些病症的同时又使人患上某些别的病症……(im:那…那是解药还是毒药啊?!)……经过我天才的努力(背景:我是天才!!),终于弄清了每种药的具体性能(路人甲:那是你自己配的吗?–),我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要根据这张清单找出能治愈所有病症的最少药剂组合……顺便说一声,病症的数目不超过10种(小呆:偶是好人吧^^),我的药是用不完的,就是说每种药剂都可以被重复使用。给你们的单子里第一行是病症的总数n,第二行是药剂的种类m(0< m< =100),以下有m行,每行有n个数字用空格隔开,文件的第i+2行的n个数字中,如果第j个数为1,就表示第i种药可以治愈病症j(如果患有这种病的话则治愈,没有这种病则无影响),如果为0表示无影响,如果为-1表示反而能使人得上这种病(无病患上,有病无影响)。我制的药任何两种性能都不同。你们只要给我用的最少的药剂数就可以了。给你们个样例:

样例输入

3
2
1 0 1
-1 1 0

样例输出

2

样例说明

  其实还有可能用尽了所有的药也不能将所有病治愈(真是不好意思嗬^^bb),那样的话你们只要写上“The patient will be dead.”就可以了。
  im:做不出来啊哇啊啊啊(暴走中)
  羽毛笔:哎呀~~im……来来吃药了。^^

解题分析

这道题拿到之后第一反应就是宽搜,但是时间肯定很恶心。既然想到了宽搜,HASH是必须要解决的。这里就用到了北京集训大牛传授的位运算。位运算的公式能有十多条,但是用不上那么多,只有皮毛的 and 和or 就解决问题。但是HASH映射方式解决了之后,会发现这其实是一道图论题。通过药物,A状态能到B状态,则AB边权值为1,最后一个spfa求单元最短路径就ok了。
先说一下hash。比如一共有三种病,那么状态的二进制表示就是111(就是(1 shl n)-1)。对应的十进制是7,于是就从7downto1,并枚举每一种药,把能连通的都连上。这里要特别注意顺序,必须是downto 否则就会悲剧。(我在这wa了好久)。
再说一下我怎么处理药的。我分为两个数组,一个治疗一个破坏(= =!)。如果值为1,则读入到治疗数组中。治疗数组的初始值为111,治疗的就变成0;如果值为-1,则读入到破坏数组中。破坏数组的初始值为0,破坏了就变成1。最后将他们转化为十进制,再用状态(7 downto 1)来or破坏and治疗,就得到了此种药对此状态的治疗后状态。注意,必须先破坏后治疗,因为如果本身有了这个病,再得,就没效果了,所以如果你本身有这个病,然后自己治好了,然后又得。。。在这又wa掉了。
最后是spfa,注意条件,就ok了。

一晚上啊,我的时间就耗在这上面了!!!不过第一次写位运算的BFS,收获还是很大的。
调试了两个小时的收获是:shl i是不可以的,要shl i-1,因为i 的初值都是1了。
因为一共只有10种病,我们就用病来代表状态。用f1[i],f2[i]分别表示能治和能得的病。f1中0表示能治,f2中1表示能得,这样新状态now2:= now and f1[i] or f2[i] and 一般是变成0,or 一般是变成1.
刚开始now=1111111…,一直变成00000…,最多也就1 shl (n-1)种情况,BFS是不会超的.

广搜+位运算+hash。
就是说我们把患病,不患病看做0、1。这样就是把n中病患与不患转换为了二进制串,按n=10来看,总共的状态就有0~2^10-1=1024种。我们假定对于第k个病,患病为1,不患为0。为了方便,我定义两个数描述一种药,那么对于药i就有a,a来描述,a的二进制如果第j位为1,表示用药i会使患上j病,a二进制如果第j为为0表示,用药i会解除j病。那么(每种状态 or a)and(a)=用i后的新状态。
hash判重我改了一下,就是说不用布尔数组。直接用step表示到i状态的最小步数,初始值为正无穷,如果到状态i的步数小于正无穷,那么就不扩展改点for i:=1 to m do

所谓的hash就是“给每个状态加个独一无二的编号,保证编号与状态的对应关系唯一”,然后开个布尔编号表。。。
状态为是否患病。。然后用药。。。。。

每种药肯定是用一次就够了~重复用是没有意义的,而顺序的问题可以无视,如以下两种情况
1 4
4 1 4
肯定是先搜到第一种情况,第二种会由于状态重复而不入队

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还能坚持

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值