题目大意:给2个数字串,给6种操作,要求最少的步数将第一串变成第二串。6种操作分别是:
1:swap0:光标位置不变,将光标位置数字与第一个数字交换;
2:swap1:光标位置不变,将光标位置数字与第六个数字交换;
3:left:如果光标不在1位置,光标左移一位;
4:right:如果光标不在6位置,光标右移一位;
5:up:光标位置不变,如果光标位置数字小于9,光标位置数字加1,否则不变;
6:down:光标位置不变,如果光标位置数字大于0,光标位置数字减一,否则不变;
题目分析:求最少步数,bfs。这题昨天晚上开始写的,今天下午AC的,到刚才灵机一动才算解决了这个问题。一开始看完题满心欢喜的拍了个双向bfs,结果华丽丽的TLE了。。。显然没有估算状态数会达到6*1000000。但实际上这题可以证明59步内一定会出解的。因为6个操作中有2对互逆操作,所以搜索的过程中会产生大量的无用状态,导致超时。一开始不想重写,不断的加优化,直到代码改的面目全非才决定重写。其实6种操作可以分成2类:1-4操作是第一类,只能改变光标位置,5-6操作能改变光标位置的数。
所以我们将改变数值的操作和改变光标位置的操作分离开来,对改变光标位置的操作进行bfs,最后与结果比较,光标经过的位置可以改变大小,每一位的改变数值的操作次数为该状态与目标状态绝对值之和。这样就能避免每一步都扩展6个状态导致不断的up,down,产生大量重复状态。而光标是从1号位置不断向右移动的,所以光标的状态可以从2^6降到10。具体可以看->这个<-。不过写的过程中又是各种粗心,各种错误搞的好不蛋疼。下午的时候终于过了。但是心情还是很沉重,因为这题还是有bug,查了网上4-5份代码,都是有bug的,有的题解说左移操作是没用的,因此没有考虑也过了。其实是错的。swap操作其实有交换相邻2个数的功能,给的2个数字串第2位第3位分别是19和91,其余4位全部相同,那么直接交换这2位显然是最快的操作,操作过程为:right-->swap0-->right-->swap0-->left-->swap0。所以左移操作是必须的!!不过如果按照网上一般的操作分离的思路做这样的数据跑出来是错的,因为还是有重复的左移操作。但是poj的数据显然不够强,所以这样写的代码都能过。虽然过了,但心里还是不舒服。又分别用A*和IDA*写了一下,由于估价函数写的很挫,本地测试已严重超时。。。刚才灵机一动,想了一下,在AC的代码上改了一下,在每个状态里面加一个标记,记录是否向左走过,如果当前状态已经向左走过,那么以后他所扩展的状态就都不向左走了,因为向左走是必须的,但不