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

【宽搜】八数码难题

2014年03月26日 ⁄ 综合 ⁄ 共 2247字 ⁄ 字号 评论关闭

题目:八数码难题 rqnoj70

题目描述

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入格式

输入初试状态,一行九个数字,空格用0表示

输出格式

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

样例输入

样例输出

 

这个游戏相信大家都应该玩过,然而这个题目的难点就是状态该怎么存,如何判断状态是否重复。。。。

这个就要用到康扩展开(可以自己百度)

接下来  就没什么难的了

Pascal Code

 

program rqnoj70;

const
  dx:array[1..4] of longint=(0,0,1,-1);
  dy:array[1..4] of longint=(1,-1,0,0);

type
  tnode=record
    node:array[1..3,1..3] of longint;
    step:longint;
  end;
  
var
  l,r:longint;
  q:array[0..1*2*3*4*5*6*7*8*9*9+10] of tnode;
  h:array[0..1*2*3*4*5*6*7*8*9*9+10] of boolean;
  first,target:tnode;

procedure init;
begin
  assign(input,'rqnoj70.in');
  assign(output,'rqnoj70.out');
  reset(input);
  rewrite(output);
end;

procedure outit;
begin
  close(input);
  close(output);
  halt;
end;

procedure readdata;
var
  i,j:longint;
  ch:char;
begin
  //初始化目标状态123804765
  with target do
  begin
    node[1,1]:=1;
    node[1,2]:=2;
    node[1,3]:=3;
    node[2,1]:=8;
    node[2,2]:=0;
    node[2,3]:=4;
    node[3,1]:=7;
    node[3,2]:=6;
    node[3,3]:=5;
  end;
  //读入初始状态
  for i:=1 to 3 do
    for j:=1 to 3 do
    begin
      read(ch);
      first.node[i,j]:=ord(ch)-ord('0');
    end;
  first.step:=-1;//入队后 +1 为 0
end;

function geth(x:tnode):longint;
var
  a:array[0..8] of longint;
  sum,num,i,j,k:longint;
begin
  a[0]:=x.node[1,1];
  a[1]:=x.node[1,2];
  a[2]:=x.node[1,3];
  a[3]:=x.node[2,1];
  a[4]:=x.node[2,2];
  a[5]:=x.node[2,3];
  a[6]:=x.node[3,1];
  a[7]:=x.node[3,2];
  a[8]:=x.node[3,3];
  sum:=0;k:=1;
  for i:=1 to 8 do
  begin
    num:=0;
    for j:=0 to i do
      if a[j]<a[i] then
        inc(num);
    k:=k*i;
    sum:=sum+num*k;
  end;
  exit(sum);
end;

procedure inq(var x:tnode);
begin
  inc(r);
  inc(x.step);
  h[geth(x)]:=true;
  q[r]:=x;
  
  if geth(x)=geth(target) then
  begin
    writeln(x.step);
    outit;
  end;
end;

function outq:tnode;
begin
  inc(l);
  exit(q[l]);
end;

procedure swap(var a,b:longint);
var t:longint;
begin
  t:=a;a:=b;b:=t;
end;

procedure kuo(var node,newnode:tnode;x,y,i:longint);
var
  newx,newy:longint;
begin
  newnode:=node;
  newx:=x+dx[i];
  newy:=y+dy[i];
  if (newx<1)or(newx>3)or(newy<1)or(newy>3) then exit;
  swap(newnode.node[x,y],newnode.node[newx,newy]);
end;

procedure main;
var
  i,j,k:longint;
  node,newnode:tnode;
begin
  inq(first);
  while l<r do
  begin
    node:=outq;
    for i:=1 to 3 do
      for j:=1 to 3 do
        if node.node[i,j]=0 then
          for k:=1 to 4 do
          begin
            kuo(node,newnode,i,j,k);
            if not h[geth(newnode)] then inq(newnode);
          end;
  end;
end;

begin
  init;
  readdata;
  main;
  outit;
end.

 

 

抱歉!评论已关闭.