hdu1043多组数据
poj1077单组数据
1、对于空间的处理
按常规方法,标志位序列vis的大小需要876543210位,空间非常大,所以我们考虑将int转化为char 类型储存(32位机int占4字节 char 占1字节)。
又考虑,如果转化为九进制,876543210(9)-->381367044(10),进一步优化空间。
可是像111111111,333333333这样的房间,根本没有被用到,却仍然占用空间,我们考虑对空间进行进一步优化。
情况个数共为9!个-->362880将标志位序列优化至此。
将每一种情况%mod以达到哈希目的,通过邻接表实现。
2、判断解的存在
设f(x)(x!=0)代表x之前小于x的数的个数,g(x)代表f(x)之和,g(x)的奇偶性决定了问题是否有解
若两状态奇偶性不同,则无法相互转化。
a、单向广搜版本
#include
#include
#include
#include
有很多地方可以压缩减小代码量,在下面的dbfs中操作
b、dbfs版本
dbfs需要修改的地方是query,当找到相同状态时我们返回当前位置序号,如果该序号在另一个队列中那么目标状态被找到,output答案
现在解释output部分
从初始状态走向目标状态时,当我们找到交点,需要递归回去从起点输出路径;从目标状态走向起始状态时,当交点出现,直接按顺序输出路径即可。
同样的,交点的走向在两种不同情况时是相反的。
(和bfs一样的部分我就不解释了)
#include
#include
#include
#include
htb[1].dir = 4;
htb[2].dir = 4;
htb[1].a[0]=str[0];
if(str[0] == 'x'){
htb[1].pos = 0;
htb[1].a[0] = '0';
}
for(int i = 1; i < 9; i ++){
scanf("%s",str);
if(str[0] == 'x'){
htb[1].pos = i;
htb[1].a[i] = '0';
continue;
}
htb[1].a[i] = str[0];
}
int hash = change(htb[1].a);
head[hash] = 1;
for(int i = 0 ; i < 8 ; ++i)
htb[2].a[i]=i+1+'0';
htb[2].a[8]='0';
hash=change(htb[2].a);
head[hash]=2;
htb[2].pos=8;if( !available(1) || !bfs()) printf("unsolvable");
printf("\n");
}
}
接下来比较dbfs与bfs的时间及空间
bfs 时间157ms 空间7836K
dbfs 时间 0ms 空间1352K
虽然程序的时间及空间会受评测机性能的影响,但是dbfs的优越性还是显而易见的。
此篇是针对上一篇dbfs入门的加深,接下来几天会更新八数码问题的idA*版本,以解决15数码问题。
(16!超过long long 范围 ,所以针对15数码,只能使用idA*算法,仍然用dbfs的话会牵扯高精度,反而增加代码的难度了)