参见下面的文章,华容道用C#写出破解后,感觉程序实在是简单,于是尝试移植到其他语言上
http://blog.csdn.net/robinspada/article/details/79354500
仅仅是简单移植,没有特别优化,运行时间如下
<?php
class Huarongdao
{
//已经走过地图类型(去重复用)
protected $history=[];
//每一步的所有走法(走到终点回溯上一步用,如果只求步数则可以不要)
protected $allNodes=[];
//下一步各种走法节点
protected $nextList=null;
protected $index=0;
const Left = -1;
const Right= 1;
const Up=-4;
const Down=4;
function Move($dir,$map, $ch, $first = true) {
$work=str_split (str_replace($ch,' ',$map));
for ($i = 0; $i < 20; $i++){
if (substr($map,$i,1) == $ch){
$pos = $i + $dir;
$x = $i % 4;
if ($dir == self::Left && $x == 0 ||
$dir == self::Right && $x == 3 ||
$pos < 0 || $pos >= 20) return;
if ($work[$pos] != ' ') return;
$work[$pos] = $ch;
}
}
$work = join($work);
//重复检查
if ($this->IsDuplicate($work)) return;
//加入下一步,记录父节点
$this->nextList[]=['map'=>$work, 'parent'=>$this->index];
if ($first){
//试着走第二步,但不能退回
if ($dir != self::Right) $this->Move(self::Left, $work, $ch, false);
if ($dir != self::Left) $this->Move(self::Right, $work, $ch, false);
if ($dir != self::Down) $this->Move(self::Up, $work, $ch, false);
if ($dir != self::Up) $this->Move(self::Down, $work, $ch, false);
}
}
function IsDuplicate($map){
$layout = $map;
//相似的形状统一成一种,去重复
$layout=str_replace('3', '1',$layout);
$layout=str_replace('4', '1',$layout);
$layout=str_replace('6', '1',$layout);
$layout=str_replace('7', '0',$layout);
$layout=str_replace('8', '0',$layout);
$layout=str_replace('9', '0',$layout);
if (array_key_exists($layout,$this->history)) return true;
$this->history[$layout]='1';
//左右镜像(大约节约1/2时间),去重复
$reverse = str_split($layout);
for ($k = 0; $k < 20; $k++){
$x = 3 - ($k % 4);
$y = intval($k / 4);
$reverse[$y * 4 + $x] = substr($layout,$k,1);
}
$reverse=join($reverse);
if (array_key_exists($reverse,$this->history)) return true;
return false;
}
function Print($index){
$outList = [];
$parent = $index;
for ($level = count($this->allNodes)-1; $level >= 0; $level--){
$outMap = $this->allNodes[$level][$parent]['map'];
$parent = $this->allNodes[$level][$parent]['parent'];
$outList[]=$outMap;
}
$cnt = 0;
for ($j = count($outList) - 1; $j >= 0; $j--){
echo "--------------------------" . $cnt++."\n";
for ($y = 0; $y < 5; $y++)
{
echo substr($outList[$j],$y * 4, 4)."\n";
}
}
}
function microtime_float(){
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function Scan(){
$initMap =
"1223".
"1223".
"4556".
"4786".
"9 0";
$curList = [ ['map'=>$initMap,'parent'=>0] ];
$begin = $this->microtime_float();
//迭代直到无路可走
while (count($curList)>0){
//记录每一步
$this->allNodes[]=$curList;
$this->nextList = [];
for($this->index = 0; $this->index < count($curList); $this->index++){
$map = $curList[$this->index]['map'];
//到达终点的判断
if (substr($map,4 * 4 + 1,1) == '2' && substr($map,4 * 4 + 2,1) == '2'){
echo "time:".($this->microtime_float() - $begin)."\n";
$this->Print($this->index);
return;
}
//穷举各种可能性,去重复,加入到下一步的节点
for ($ch = '0'; $ch <= '9'; $ch++){
$this->Move(self::Left,$map, $ch);
$this->Move(self::Right, $map, $ch);
$this->Move(self::Up, $map, $ch);
$this->Move(self::Down, $map, $ch);
}
}
//迭代
$curList = $this->nextList;
}
echo "无解";
}
}
(new Huarongdao())->Scan();
?>