月度归档:2014年02月

[POJ 1093]

Formatting Text

DP

题意:输入行长度值n,以及一篇文章,要将文章重新排版,使得”坏值”和最小。若某行只含一个单词,则坏值为500。包含多个单词的行,单词间每个长度为k的间隔,其坏值为(k-1)^2。

这题之前做CLRS时见过类似的(第二版习题15-2),当时也是想了很久才推出公式:用dp[i][j]保存到第i行结束时,打印了前j个单词的最小坏值。那么dp[i][j]=min{dp[i-1][k-1]+bd[n-sum{w[l]|k<=l<=j}][j-k]},其中w[l]为第l个单词的长度,bd[p][q]为预处理计算出来的一行有p个空格和q个间隔时的坏值。状态转移时注意下标边界,并需要记录父状态。这里对于相同坏值的方案,要输出使各间隔长度值字典序最小的,那么每次dp使,总是使更多单词尽量在之前打印即可。 输出时,首先找到最小坏值对应的行数,根据父状态一层层回退,记录每行要打印多少个单词;然后逐个单词处理输出即可。

ps: 这题考察的算法貌似很有实用价值呢……不过现在的文本处理程序,恐怕是要比这复杂十倍以上的吧……

[POJ 1324]

Holedox Moving

搜索 + 滚动hash

给出最大20*20的格盘,和一条长为l的蛇,目的是使蛇头移动到(1,1)。格盘中存在k个格子是无法通过的石头,蛇也不能碰到自己的身体,包括最尾的一格。若能到(1,1),输出最短距离,否则输出-1。

考虑保存蛇的状态时,只保存其蛇头位置,以及指向之前蛇头的指针。由此就能搜索处理蛇的移动方案。考虑判重时,使用滚动hash,即到一个新状态时,将之前蛇头对应的hash值升位并减去之前蛇尾的部分,再加上新的蛇头值即可。

另外就是,可以考虑优先向(1,1)的方向移动,以及搜索之前先判断蛇头是否可达(1,1)。

[POJ 1872]

A Dicey Problem

广搜

题意:有一个最大10*10的格盘,上面有一个标准色子。规定如果色子朝上的一面和相邻的某盘格的数字相同,或者盘格数字为-1,那么色子可以朝该方向滚动一格。问是否存在一条路径,使色子在格盘上从初始位置出发后,还能回到初始位置。若有解则数据保证只有唯一解。最后还要输出滚动方案。

这是1999年World Finals的C题……读完题面后很容易发现数据规模不大,状态转移不多,不需要特别优化。相比起来,需要花费更多时间考虑的是数据结构的表示。

色子有6面,但其姿态可以由正面和顶面两个数字来唯一确定,总共有6*4=24种可能。盘面最多100个格子,因此搜索空间是2400。可以将盘面状态表示为:((正面值-1)*6+(顶点值-1))*100+(纵坐标-1)*10+(横坐标-1)。当从队列中取出一个状态时,先由正面和顶点值得到整个色子当前6个面的值,这里可以将6个面分别编号,然后按六进制的方式(或者每个数用3位表示,移位处理)压成一个整型,再打表处理。然后模拟4个方向的滚动,求6个面的新值,再判断在该方向上的盘面值是否允许滚动。当回到原点时,返回当前状态以便回溯输出解方案。

一开始考虑时,直接用了全部六个面的值和坐标来作为状态,这样d和p数组的大小都是6^6*10*10=4665600,正常来说这也不是一个太大的值。但是这题test cases非常多。每次都memset的话,就超时了。因此只能在不丢失信息的情况下尽量压缩状态。

[POJ 1069]

The Bermuda Triangle

搜索

题意:给出一个边长以三角形个数描述的正六边形,以及n种正三角形,问该六边形能否刚好由这些三角形完全覆盖。

放假都没做题,有点手生。由于提示是搜索题,首先考虑问题建模。可以将每个小三角形的覆盖情况用1bit表示,那么六边形的每行就可以用一个位向量来描述。用作覆盖的三角形只会是正置或倒置。于是,问题就转化成了由上到下由左到右地依次尝试用各种三角形进行填充。

需要注意的是,正六边形是对称的,可以分解成6个正三角形或3个菱形,直接判断后者的完全覆盖情况即可。对于此题数据,只分解成正三角形会WA,分解成菱形可以AC。另外,如果是原来的正六边形,一行最多会有25*4-1=99个小三角形,就无法用64位的LL来表示了。而菱形的话,一行最多为25*2=50位,还是可以的,写起来也较易实现。

ps: 这个假期过得太开心了……发生了不少好事情,希望不会是把一年的运气都一下子用光了吧…………那么接下来,就是要好好准备3月中旬的校赛了。