300 likes | 427 Views
Bugs Integrated, Inc. 解题报告. 00001054 胡华嵩. 一、算法设计. 用动态规划的思想 所有的 “ 方块 ” 的坐标值都减 1 ,则坐标满足 0≤x≤N-1 0≤y≤M-1 每个方块就用一个有序 2 元组表示 (x,y) x,y 满足上面两个式子. 定义 1. 设向量 B=(b 0 ,b 1 , … ,b M-1 ) , S(B) 表示一个由方块组成的集合。严格的定义如下: S(B)={(x,y)|x≤b y }
E N D
Bugs Integrated, Inc. 解题报告 00001054 胡华嵩
一、算法设计 • 用动态规划的思想 • 所有的“方块”的坐标值都减1,则坐标满足 0≤x≤N-1 0≤y≤M-1 • 每个方块就用一个有序2元组表示 (x,y) x,y满足上面两个式子
定义1 • 设向量B=(b0,b1,…,bM-1),S(B)表示一个由方块组成的集合。严格的定义如下: S(B)={(x,y)|x≤by} 如果把B看成是一个边界的话,S(B)表示的就是边界B左边的所有部分,我们可以从下图看出:
定义 2 • 对于每个(x,y),我们定义一个以(x,y)为边界的集合,记为B(x,y)。严格的定义如下: S(B(x,y))=S(Bx,y) 其中Bx,y为定义1中的向量,且满足 b0=b1=…=by=x by+1=…=bM-1=x-1
定义3 • 设P=(p0,p1,…,pM-1),其中0≤pi≤2。我们规定 S(B-P)=S((b0-p0,b1-p1,…,bM-1-pM-1)) 相当于是在S(B)的基础上,除去了每一行最右边的0(1,2)个方块。 • 后面我们也用S(B-P)表示在S(B-P)中能容纳的3x2矩形的最大数目。
把P的第i个分量看成是3进制数 的第i位,则每个M维向量P与0 到3M-1中的一个数p一一对应。 我们计算每个x,y,p所对应的S(B(x,y)-P)中所能包含的3x2矩 形的最多数目。
为了下面讨论方便,还需要几点说明: • Ej表示一个定义3中的向量,其中只有第j个分量的值为1,剩下的全为0。与Ej相对应的数为3j。 • “0”表示的也是一个定义3中的向量,其中所有的分量都为0。与0相对应的数就是0。在下面的分析中0和0不加区分(即都用“0”表示)。 • 对于任意的一个p,pj表示与p对应的向量P的第j个分量的值。 • 设p与P对应,A(x,y,p)的值为S(B(x,y)-P)中包含3x2矩形的最多数目。
给定x,y,p • 有两种情况: pj>0 和 pj=0 • 对于pj>0的情况,我们以右边的两个图为例: • 容易看出: A(x,y,p)=S(B(x,y)-P) =S(B(x,y-1)-(P-Ey)) =A(x,y-1,p-3y)
对于pj=0,又分三种情况: • 1 以(x,y)为右下角不能放3x2矩形 • 2 以(x,y)为右下角能放一个横着的3x2矩形 • 3 以(x,y)为右下角能放一个竖着的3x2矩形 • 当然,2、3两种情况都需要x,y满足一定的条件 • 对于第一种情况,(x,y)显然是多余的,加上(x,y)与不加上(x,y)是等价的,即 A(x,y,p)=S(B(x,y)-P) =S(B(x,y-1)-P) =A(x,y-1,p)
第二种情况 • 很显然,要使第二种情况成立,p的值需要一定的条件,即 py-1=0 • 从右图可以得到下面的结论: A(x,y,p)=S(B(x,y)-P) =S(B(x,y-2)-(P+2x Ey-1+2xEy))+1 =A(x,y-2,p+2x3y-1 +2x3y)+1
第三种情况 • 同上,也需要p满足一定的条件: py-1=py-2=0 • 由右图可得下面的结论: A(x,y,p)=S(B(x,y)-P) =S(B(x,y-3)-(P+Ey+ Ey-1+Ey-2))+1 =A(x,y-3,p+3y-2+ 3y-1+3y)+1
在任何状态下,都先要考虑第一种情况,如果满足第二或第三种情况的条件,则应该取几种情况的最大值。在任何状态下,都先要考虑第一种情况,如果满足第二或第三种情况的条件,则应该取几种情况的最大值。 • 上面的讨论中,考虑的y是大于1的,对于y等于0和1,可得同样的结论。x=0的初始值全为0,所以只需考虑x>0的情况。 • 由上面的讨论可知,我们只需要记录最后3个方块(x,y)的数据,就可以一步一步的推到最后,而A(N-1,M-1,0)就是我们所要求的答案。 • 算法的时间复杂度为O(MN3M)
二、优化 • 150x10x59049≈9x107 • 运算时间60s左右 • 对于每个(x,y),都要计算所有的p对应的P的第y个分量(还有y-1、y-2)的值,这里重复计算很多。我们可以事先计算好每个p的各个分量的值。这样处理以后,时间减少到了15s左右。 • 再通过一些细节的更改,最后时间能减少到8.5s。
三、进一步分析 • 从M,N,P三个数上着手 • M最大为10,没什么好考虑的 • N最大为150,N减少1,将减少M3M次循环,我们考虑一个6xM(2≤M)的子区域,如果这其中没有坏的方块,则这个子区域能被2x3的矩形填满。如果题目给的数据中存在这样一个区域,我们可以把这个区域挖去,求得剩下的部分所能达到的最大值,再加上M,就应该是最后的答案。但是这样编出的程序Wrong Answer。
分析原因 • 问题在于:我们要求的6xM的子区域的边界是规则的,而实际中如果子区域两边都是不占用子区域的最优情况,则有可能出现两边都浪费了2x2的小区域的情况,并且它们不是平行的,连接到一起仍然不能组成一个新的3x2,这样就少计算了。 • 如果改成要求8xM或10xM,仍然会出现类似的情况。再大的区域就没有意义了,即使算法正确,出现这样的数据的可能性也太小了。
再考虑P • 考虑右边这种情况:它表示P的一个局部。 • 图中阴影部分对于摆放3x2矩形没有任何的贡献,所以这种情况的值可以不用计算。 • 我们用212来表示这个局部情况
初步考虑 • 类似的情况还有几种:101、102、201、202 • 0到59049中存在着上面5种情况的数一共有 49300个,也就是说我们需要计算的只有不到10000个。对于那些没有计算的,在后面的递推中有可能用到。我们可以用一个数组记录与每个不需要计算的p等价的p’的值(需要计算的值就是本身)。当需要用到p的时候,直接取p’的值即可。
错 • 上面的考虑是错误的 考察右图,分别是101和102的情况,它们在S(B(x,y)-P)的(x,y)处出现了问题,即那个小方块对3x2矩形有贡献,不能拿掉。 • 类似的,212也会出现这样的情况。
没关系 • 我们需要计算212、101、102这三种情况,只能去掉201、202这两种情况。 • 0到59049存在201、202形状的数有27936个,仍然能少计算很多。 • 我在耗时最短的程序的基础上进行修改,然后提交……
Ft! • 耗时10s • 前面预先需要处理的过程耗时不到0.1s • 计算150,10,0这组数据: 未改过的耗时最短的程序需要1.6s 改过的耗时最短的程序需要1.8s • ……
四、关于标程 • 2个标程:c语言的在限时80s的情况下超时,pascal语言的wrong answer • Pascal没细看,应该就是前面的算法。 • C语言用的方法和上面所说的类似,只不过是一列一列的考虑,对于每一列从第一行开始判断,对于每种情况再对下一行递归调用,直到最后一行。 • 下面简要的说说:
我们只考虑已经处理过的最后两列和当前列。 • S(B(x0))定义与前面类似,表示以x0-2为边界的左边部分 • P的定义完全一样 • 有四种情况: (x-3,y,x-1,y+1) (x-2,y,x,y+1) (x-2,y,x-1,y+2) (x-1,y,x,y+2) 构成新的3x2矩形。 (左图显示了3种)
五个参数的递归调用 srot(x,y,low,high,plus) x即当前列数,在随后的调用中不改变 low、high都是一个P类型的向量 plus表示当前处理过的行中已经增加了多少个3x2的矩形 y即当前行数,当y=M,则将 S(B(x-2)+low)+plus的值与S(B(x)+high)的值比较,去较大值赋给S(B(x)+high)
一小段程序 • srot(x, y+1, low+2*na[y], high, plus); srot(x, y+1, low+2*na[y], high+na[y], plus); srot(x, y+1, low+2*na[y], high+2*na[y], plus); • 若是(x-3,y,x-1,y+1)存在一个3x2矩形 srot(x, y+2, low, high+na[y]+na[y+1], plus+1); srot(x, y+2, low, high+2*na[y]+na[y+1], plus+1); srot(x, y+2, low, high+na[y]+2*na[y+1], plus+1); srot(x, y+2, low, high+2*na[y]+2*na[y+1], plus+1); • 其他情况类似
一直计算到第N-2列,此时S(B(N-2)+3M-1)就是所要求的结果。一直计算到第N-2列,此时S(B(N-2)+3M-1)就是所要求的结果。
五、题外话 • 课程主页上有这道题的解题报告,里面算法说得很清楚,所以实现起来很容易。但是如何优化就需要认真去考虑。我一开始选这道题作解题报告,主要是想看看助教的8s的程序是怎么编的。我觉得看了助教的这个程序,比我自己去Judge Online上做出10道题学到的东西还要多。这一点都不夸张,因为只有把不会的东西转变成会的才是进步。