题意就不细说了,背景和玩法和模拟细节就是 经典小游戏十滴水(http://www.7k7k.com/swf/15746.htm),大家自己去玩就行。
约定:以下文字中,称题面里的waterdrop为水滴,small drops为水珠。
题目描述里遗漏了很多细节,这里根据比赛里正确的Clarification里的回应补充一下:
- 初始爆炸位置和其他有水滴的位置都互不重叠(都在不同位置上)
- 每个水滴的初始大小为1~4的整数
- 水珠撞到边上的时候直接消失,不反弹
- 某一秒,水滴体积大于4就在这一秒炸裂,炸裂的时候只会产生4个体积为1的水珠(守恒是什么,可以吃吗?反正游戏规则这么来的)
- 水珠撞到水滴的时候会被吸收,水滴吸收完这一秒到它上的水珠后再考虑是否炸裂
- 水滴炸裂后就当不存在了
- (x,y)位置的水滴在第T秒破裂后,四个小水珠在第T秒都在(x,y),不过运动方向不同
- 关于(x,y)的坐标系方向:左上角为(1,1),向下x增大,向右y增大(或者说,r约束x的范围,c约束y的范围)(这个地方值得吐槽比赛时的出题人,懒得理人就算了,之后答了别人类似的问题还打错了,顺利的误导人了是什么样的心态)
接下来讨论一下这种推演一定时间后的情况的模拟题应该如何去实现。一般有2种思路:
- 每一秒,检查每个水滴和水珠的状态,应该移动的移动,应该炸裂的炸裂
- 当水珠撞上水滴的时候,做相应处理:改被吸收的吸收掉,该炸裂的炸裂,该继续前进的继续前进
个人喜好,称前者为时间驱动的模拟,后者为事件驱动的模拟。
下面来讨论一下这两种模拟的具体实现:
1. 时间驱动的模拟
一般的实现思路就和梦幻西游、问道这类回合制游戏类似:维护一个对象队列,每一秒轮训每个对象(或者说,扫一遍这个对象队列),访问到的对象采取相应的行动。
注意到,在这题里,水珠是同时移动的对象,并没有什么同一秒内还先来后到的情况。
可以这样处理:先判断水珠是继续向前还是被吸收,采取相应行动,然后检查每个水滴是否应该爆炸。
这样实现,时间复杂度是O(Tn)
代码如下: