回 帖 发 新 帖 刷新版面

主题:请求援助!!!!!!!!急!

作业4、八数码问题(work4.pas,输入文件:work4.in,输出文件:work4.out)
问题描述:
如下图所示,给出3×3的9个方格,现将1~8这8个自然数填入方格中,给定一个初始状态,例如为:023184765(如左图),其中空方格用数字0表示。现允许移动空格,但每次只能移动1格。试编程完成对于任意给定的一个目标状态(如右图),能够以最少步数实现从初始状态到目标状态的转换。
0    2    3                    1    2    3
1    8    4     ------->       8    0    4
7    6    5              7    6    5


输入输出格式:
输入两行,分别表示初始状态个目标状态。
如果有解,则输出移动得到解的过程,否则输出:“no solution!”,不包括引号。

输入样例:
023184765
123804765

输出样例:
023184765
123084765
123804765

回复列表 (共1个回复)

沙发

program num8_str1; 
uses Crt; 
type a33:array[1..3,1..3] Of byte; 
{3X3的二维数组,用于存放棋盘布局} 
a4=array[1..4] of shortint; 
node=record {定义数据库中每个元素记录类型结构} 
ch: a33; 
si, sj: byte; 
pnt, dep: byte; 
end; 
const goal:a33 = ((1,2,3), (8,0,4), (7,6,5)); {目标布局} 
start:a33 =((2,8,3), (1,6,4), (7,0,5)); {初始布局} 
di:a4=(0,-1, 0, 1); 
dj:a4=(-1, 0, 1, 0); 
var data:array[1..100] of node; 
temp: node; 
r, k, ni, nj, Head, Tail, depth: integer; 
{变量depth存放当前搜索深度} 
function check(k: integer) :boolean; { 检查某步移动是否可行} 
begin 
hi:=temp.si+di[k] ; nj:=temp.sj+dj[k]; 
if (ni in [1..3]) and (nj in [1..3]) {~移动后新位置仍在棋盘中} 
then check:=true else check:= false; 
end; 
function dupe: boolean; { 检查队尾新存入布局是否已在队列中存在} 
var i,j, k: integer; 
buf:boolean; 
Begin 
buf:= false; i: = 0; 
{变量将i依次指向队列中的各个布局(最后一个除外)的位置} 
repeat 
inc(i) ;buf:= true; 
for j:=1 to 3 do 
for k:=1 to 3 do 
if data[i].ch[j,k] < >data[tail].ch[j,k] 
{data[tail]是队列中最后一个元素,即新产生的布局} 
then bur:= false; 
until buf or (i> = tail-1); 
{buf=truee新布局与队列中布局有重复} 
dupe:= buf 
end; 
function goals: boolean; { 比较是否达到目标布局状态} 
var i,j :byte; 
begin 
goals:= true; 
for i:=1 to 3 do 
for j:=1 to 3 do 
if data[tail].ch[i,j] < >goa1[i,j] 
then goals:=false {未达到目标布局} 
end; 
procedure trace; 
var i,j :byte; 
begin 
write( 'cl=', Head,' op=', tail); 
writeln('dep=',depth,'k=',k); 
fori:=1 to 3 do 
begin 
for j:= 1 to 3 do write(data[tail], ch[i,j]); 
writeln end; 
end; 
procedure print; {输出移动步骤} 
var buf: array[1..100] of integer; 
{数组buf存放起始态、目标态以及从起始态到目标态所经过的各态的位置} 
i,j, k, n: integer; 
begin 
n:= 1; 
i:= tail;buf[1]:= i; {buf[1]中是目标布局在队列中位置} 
repeat 
j:=data[i].pnt; {data[I].pnt的值是布局I的父结点的位置} 
inc(n); buf[n]:=j; i:=j 
until i=0; {根结点(初态)的父结点为0,即I=0} 
writeln(' staps:', depth + 1); 
for i:= 1 to 3 do {打印棋盘布局} 
begin 
for k:=n-1 down to 1 do 
begin 
for j:= 1 to 3 do write(data[buf[k]].ch[i,j]); 
if i = 2 then write( ' - > ') else write(' '); 
end; 
writeln; 
end; 
readln; halt 
end; 
{ main program = } 
begin 
Head:= 0; tail:= 1; 
with data[1] do {队列中存入第一个元素(初始状态)} 
begin ch:= start; si:= 3; sj:= 2; 
pnt:= 0; dep:= 0; 
end; 
repeat 
inc(Head);temp:=data[Head]; {取队首记录} 
depth:= temp.dep; 
for r:= 1 to 4 do {对取出记录进行扩展} 
if check(r) then {布局中空格向某方向移动成功} 
begin 
inc(tail);data[tail]:= temp; {新产生布局存入队尾} 
with data[tail] do 
begin ch[si,si]:= ch[nj,nj]; 
ch[ni,nj]:=0;si:=nj;si:=nj; 
pnt:=Head;{记录此布局的上一布局在队列中的位置} 
dep:= depth + 1;{记录本布局的搜索深度} 
end; 
trace; 
if dupe then dec(tail) {dec(tail删除新产生的结点)} 
else if goals then print; 
end; 
until Head>=tail; {队列空} 
writeln('no solution');readln 
end

我来回复

您尚未登录,请登录后再回复。点此登录或注册