题目:八数码难题 rqnoj70
题目描述
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入格式
输入初试状态,一行九个数字,空格用0表示
输出格式
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入
283104765
样例输出
4
这个游戏相信大家都应该玩过,然而这个题目的难点就是状态该怎么存,如何判断状态是否重复。。。。
所以在这之前大家先去看看 康托展开http://www.cnblogs.com/oijzh/articles/2645137.html
接下来 就没什么难的了
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.