ACM练级日志:HDU 4433 Locker

来源:互联网 发布:rds 慢sql 编辑:程序博客网 时间:2024/06/05 05:02

天津现场赛的一道题,说有两个密码串,每次你可以转第一个串连着的最多三个数,问最少转多少次能把第一串转成第二串。

开始以为是搜索,后来一看n<=1000直接吓尿…… 后来以为是字符串,但是怎么做也做不出来,尝试了贪心,也没什么好的策略……最后查了一下别人的解题报告才想起来是DP,一次连续转三个这么逗的条件还真像是给DP用的……


不过我的DP跟他们都不太一样,听说有人用f[i][x][y][z]表示:目前在i的位置,当前是z,前一个是y,再前一个是x,这样的话每次想办法把z转对了以后,就可以转移到f[i-1][ a[i-3] ] [x][y] 之类的了,转两个、三个改改x和y就好,应该说相当简洁明了,但是作者说他TLE了……  的确,虽然这么定义的话,状态复杂度是1000x10x10x10=100 0000,再乘以转移复杂度100(一会说)的话就是10 0000 0000, 乘上常数就相当勉强了,但是我用了记忆化搜索的写法,就不会出现这个事了…… 因为第二维实际上是给你看的,并不参与什么运算,起到的是一个辅助作用。记忆化搜索风格就是这点好,能不用访问肯定没戏的状态。


很多人不明白样例2那个12怎么算出来的,我一开始也是怎么算都是13,这跟转移方程的一点也有关系,就是你千万不要这么转:试着只转z把z弄对、转两个把z弄对、转三个把z弄对  这三个取一个最小值,这是不对的,最好的例子就是52 86,答案是4,这就是因为你要先两个都转3次,再单转个位一次,也就是说这三种操作在把当前位弄对这个过程中是完全可能混合出现的。怎么办呢?只能枚举在转z的过程中,x和y各沾了多少光了。所以转移复杂度并不是o(1)的,而是o(10x10)的。


具体实现的时候还要注意i-3超解的情况,注意到这里的时候特判一下。


记忆化搜索本来我觉得可能还是挺悬的,想再加点优化,结果直接500ms过了……


0 0
原创粉丝点击