HDU5396 / 15多校9-1 Expression

题意

给出了一个算术表达式,表达式里面只会含有加减乘三种运算。我们每一次从中选取两个数字并执行这两个数字对应的运算,运算结果放回式子中继续进行运算,直到最后只剩下了一个数。让我们求的是每一种不同的选取方式所得到的结果的和。

注意

这个题没有做好的主要原因是没有领会到题目中关于不同的选取方式的定义,注意到题目中讲到只要有一轮选取的数字不一样,就视为不同。这句话的含义中有两个信息:一是允许重复,二是要分先后

思路

最开始确实是没什么思路的,后来看了看board发现并不是特别难的题。于是尝试拆解问题,我们可以从算数式的一小段入手,以sample的1 + 4 * 6 – 8 * 3为例。

只考虑1 + 4部分,只有一种配置方法,就是(1 + 4);
考虑1 + 4 * 6部分,我们发现这一部分可以看成两种情况:1 + (4 * 6)和(1 + 4) * 6,在这里面我们已经考虑了1 + 4区段,而4 * 6区段只有一种配置。这样1 + 4 * 6这个区段就有两种配置了。
接下来考虑1 + 4 * 6 – 8区段,要想得到这个区段的全部情况,我们应该考虑:
1 + (4 * 6 – 8),1 + 4 * (6 – 8),(1 + 4) * 6 – 8,(1 + 4 * 6) – 8这些情况,其中(4 * 6 – 8)又可以看成考虑(4 * 6) – 8,4 * (6 – 8)这两种情况,而(1 + 4 * 6)的对应情况我们先前已经算好了。
最后,考虑1 + 4 * 6 – 8 * 3,顺着上面的思路来,就可以拆分成:
1 + (4 * 6 – 8 * 3),1 + 4 * (6 – 8 * 3),(1 + 4) * 6 – (8 * 3),(1 + 4 * 6) – 8 * 3,(1 + 4 * 6 – 8) * 3,接下来再去拆分这五种情况中的子情况。。。

如果比较敏感的话应该已经发现这就是典型的区间dp了,在推方程的时候,我们是将所有子情况的答案累加,得到当前情况的答案,但这还不够,还要注意每种情况,因为选择顺序的关系,会有多重副本,而这个副本的数量其实蛮好求,就是阶乘,而还要注意,我们在讨论当前情况的时候,是将整个等待处理的算式区段分成了(左区段)算子(分界点)算子(右区段)这样看待的,那么先后的问题又来了,我们不光左右区段的答案自身要乘上阶乘,最后整个结果还要乘上一个组合数,因为左右区段的操作又是分先后的。

以下引自官方题解,注意第2段第2行的dp[l][r]实际上是dp[l][k]

 

QQ20150820-1@2x

代码

测试数据

 

15多校2-9/HDU 5308 I Wanna Become A 24-Point Master

更新

根据出题人的回复,问题应该已经修复了,本文代码中的PATCH部分可以忽略。关于原来出现的问题的证明也已经失效,敬请留意。

题意

给出一个数字n,问你如果给你n个n,你要怎么样才能利用加减乘除运算给算成24呢?注意,没个数字只能使用一次,所有的数字必须都要用到。你要按照题里面介绍的特别的表示方法把你的解法表示出来。除法是可以出分数的,因为是SPJ,应该可以过。

思路

我个人不太认同出题人题解里面给出的手算4~15的所有情况,对于较大的数再机智得直接消除凑24,因为手算的太多了。

我的思路是对于比较小的情况,即n <= 27的时候,可以直接利用dfs找出答案。因为题目给出的表示方法其实意外地适合dfs的搜索过程,我们不断的枚举下一个操作,即从当前没用过的数里面选出两个,然后尝试加减乘除,每一次尝试就是改变当前数组尾部的值,同时做好标记进入下一层。只要搜索成功,我们就可以在dfs的退出过程中将路径保存下来,开一个stack,把这些个结果压进去, 输出的时候弹出来,顺序就正好是正序了。

对于比较大的情况,事情就变得非常简单,假如说现在的n = k,那么只要找出24个相同的数k,加到一起,就是24 * k了,然后再额外拿一个k,做一下商,就得到了24,对于多出来的数,我们可以找两个k做一下差得0,然后用得到的0去乘上下一个多余的数,最后剩下一个0,和刚才的24加一下,多余的数也消耗掉了。

注意点

做这个题的时候发生了两处失误,首先是dfs的时候,范围设置的不正确,两层的循环都应该是从1开始的,原来外层从1开始而内层却是从i+1开始(i是外层的循环变量),这样显然丢解了,而且搜索速度也拖慢了。

其次是题目中要求每个数只可以用一次,结果我偷懒把一个0跟好多哥数字去乘了,这样肯定就错了。

然后dfs应该采取一些必要的优化,比如说跳过重复的区段(剪枝),如果不做的话可能超时。如果实在没办法,打表也可以,反正才24种情况,并不会被拒绝提交。

然而还是没过

折腾了一下午后发现很有可能这个题的评测器在实现上有漏洞,通过排(feng)除(kuang)法(jiao),发现有3组数据没有通过评测器,但是确实是正确的。

如果数据确实不符合题意,请与我跟进,谢谢。

代码

为了过,最后没有办法特殊对待给上面三组数据打了补丁。

标准答案里边很豪放地用了分数,正常来讲评测器应该是接受分数的,但不知道为什么不接受我这个调换位置保证不出现分数的答案了,真的很怪。我自己写了一个检查我自己答案的评测器,没有提供对分数的支持,但是评测器会在发现出现分数的时候报错,因为我的答案是已经调换顺序保证不出分数的了,此外也检查了每个数字的使用情况,保证和题意一致。

从1开始测了1个GB的数据,没发现问题,如果评测器有问题,请跟进,谢谢。

如果你还是不相信我

下面是官方题解:

QQ20150723-1@2x

 

 

虽然很蛋疼,写这么多其实就是为了让这么个玩意别再坑更多的人了。

Scroll to top