这是在codeforces上参加的第二场比赛了,虽然最后测评的结果显示在房间排名是第二名,但是与第一名的差距之大却是很难看的。这里,简单地报告一下E题Summer Reading的两种解法。比赛完后,看了作者提供的tutorial仍然是一脸雾水,主要是因为误解block为输入中连续的数字块。之后,借鉴了牛人的代码,才知道block其实是指一本书号的数字块。如给定输入序列为0 0 2 2 3 3 0 0 4 4 0,这其中就存在着三个block,即2 2;3 3;4 ;而非两个block(2 2 3 3;4 ;)。
解法一(思想源于作者的tutorial):
根据作者提供的DP思想,对于每一个block都可以尝试进行向左或向右扩展,如 4 可以向左扩展为 4 4 4 ,然后再向右扩展,就变为了 4 4 4 4 ,并且符号题中所给条件。对于一个特定的block[i]来说,其向左扩展的限制在于其左边的block[i-1]的向右扩展结果,block[i-1]与block[i]间缺少的书号,以及block[i-1]后面紧跟着的0的个数,而其向右扩展的限制在于其向左扩展的结果以及block[i]后面紧跟着的0的个数。
示例:0 0 2 2 3 3 0 0 4 0
block[1] = 2 2,此时已无法向左扩展(即向左扩展0位),因为必须block[1]之前缺少的书号的数目为1(即只有书号1缺失),至少要占据两个0。并且由于block[1]后面没有紧跟着的0,所以向右也无法扩展。
block[2] = 3 3,向左无法扩展,因为block[1]与block[2]之间没有0存在。向右可以扩展1位或者2位,都不会打破题中的限制。
block[3] = 4 4,向左扩展讨论:在block[2]扩展1位的情况下,block[3]向左扩展1位;在block[2]扩展2位的情况下,block[3]向左无扩展(即扩展0位)。向右扩展讨论:在block[3]向左扩展1位或者2位的情况下,block[3]向右扩展1位,或者不扩展。
在block[3]向左不扩展时,block[4]向右扩展1位。
在上述block扩展的过程中,如果有一个block不管是向右扩展几位(包括扩展0位)都无法满足题中条件时,就直接输出-1,并退出执行。否则,就可以利用block的扩展情况进行还原书号序列。
下面用两个数组exLeft和exRight来分别表示每个block的向左扩展情况和向右扩展情况。为了方便,令block[1]之前还存在着一个block[0]。
block[0]:为了不占用block[0]后面的零,令exRight[0][0]= true,exRight[0][1-4] = false
block[1]:exLeft[1][0] = true,exLeft[1][1-4]= false(block[1]无法向左扩展);同理,exRight[1][0]= true,exRight[1][1-4] = false。
block[2]:exLeft[2][0] = true,exLeft[2][1-4]= false;exRight[2][0-2] = true,exRight[2][3-4]= false(block[2]向右扩展1位或者2位均可)。
block[3]:exLeft[3][0-1] = true,exLeft[3][2-4]= false;exRight[3][0-1] = true,exRight[3][2-4]= false(exRight[3][0] = true对应于exLeft[3][1]= true,而exRight[3][1] = true对应于exLeft[3][0]= true或者exLeft[3][1] = true)。
对于最后一个block,为了使得留出更多的0来填充更大的书号,我们要使用exRight[3][i] = true最小的那个i,即i= 0,但由于此时只剩下一个0,无法完整填充更大的书号,所以i=1。接着寻找可以与exRight[3][1]= true相对应的exLeft[3][j],然后利用exLeft[3][j]找到可以与其相对应的exRight[2][k],如此递归下去。对于每个block,利用找到的合适的exLeft和exRight进行向左、向右扩展,完成书号的填充。
在编码过程中,exLeft[i][j]里面可以记录可以与其相对应的一个exRight[i-1][k]中的k值,这样就可以快速向前递归填充了。
代码:
#include
#include
#include
#include
#include
#include
#include
解法二:构造解
把Vasya做n天的SummerReading想象成骑车穿过n米的长路。那么Vasya最快的方式是每隔两米,速度就增加1,最慢的方式是每隔五米,速度才增加1。输入中的非零数代表Vasya在此点时的速度。如果这个非零值小于Vasya以最慢的方式达到此点的速度,或者大于Vasya以最快的方式达到此点的速度,那么肯定是不合法的。
示例:0 0 2 2 3 3 0 0 4 4 0
最快方式:1 1 2 2 3 3 4 4 4 4 5
最慢方式:1 1 2 2 3 3 4 4 4 4 4
根据题中要求对于出现的书号,至少要出现两次。所以,对于达到的速度值至少要出现两次。最快的方式里面5只出现一次,为了满足条件,必须减1。最快方式就变成了 1 1 2 2 3 3 4 4 4 4 4。