现在的位置: 首页 > 综合 > 正文

poj1077

2018年01月15日 ⁄ 综合 ⁄ 共 1406字 ⁄ 字号 评论关闭

【题意】

经典的八数码问题。

描述了一个3*3的格子,每个格子里有一个数,还有一个空位,

每次操作可以将空位跟周围的格子里的数交换,问最少多少次操作可以使方格变为

1 2 3

4 5 6

7 8 x

有解打出最少的操作序列

无解打unsolvable

【输入】

一行,表示格子里的数

【输出】

有解打出最少的操作序列

无解打unsolvable

启发式搜索,IDA*算法

估价函数为每个点到自己位置的哈密顿距离之和

program poj1077;
const
  zl:array [1..4,1..2] of longint=((0,1),(1,0),(-1,0),(0,-1));
  change:array [1..4] of char=('d','r','u','l');
type
  status=array [0..4,0..4] of longint;
var
  i,j,k,deep,x,y:longint;
  square:status;
  temp:char;
  yes:boolean;
  solution:array [0..101] of longint;
procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;
function h (now:status):longint;
var
  i,j,k:longint;
begin
  k:=0;
  for i:=1 to 3 do
    for j:=1 to 3 do
      if now[i,j]<>9 then
      k:=k+abs((now[i,j]-1) div 3 +1-i)+abs((now[i,j]-1) mod 3 +1-j);
  h:=k;
end;
procedure dfs (x,y,g,lasth,last:longint);
var
  i,j,k,nx,ny:longint;
begin
  k:=h(square);
  if k+g>deep then exit;
  if k=0 then
    begin
      yes:=true;
      exit;
    end;
  for i:=1 to 4 do
    if i+last<>5 then
    begin
      nx:=x+zl[i,1];
      ny:=y+zl[i,2];
      if (nx>3)or(nx<1)or(ny>3)or(ny<1) then continue;
      swap(square[x,y],square[nx,ny]);
      solution[g+1]:=i;
      dfs(nx,ny,g+1,k,i);
      swap(square[x,y],square[nx,ny]);
      if yes then exit;
    end;
end;
function idastar(deep:longint):boolean;
begin
  yes:=false;
  dfs(x,y,0,deep,0);
  idastar:=yes;
end;
begin
  for i:=1 to 3 do
    for j:=1 to 3 do
      begin
        read(temp);
        if temp='x' then
          begin
            square[i,j]:=9;
            x:=i;
            y:=j;
          end
                    else
          square[i,j]:=ord(temp)-48;
        read(temp);
      end;
  deep:=h(square);
  while not idastar(deep) do
    inc(deep);
  if deep>100 then
    begin
      writeln('unsolvable');
      exit;
    end;
  for i:=1 to deep do
    write(change[solution[i]]);
  writeln;
end.
【上篇】
【下篇】

抱歉!评论已关闭.