【聪明的打字员】
阿兰是某机密部门的打字员,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0, Swap1, Up, Down, Left, Right,定义录入区的6个位置的编号,从左至右依次为1,2,3,4,5,6。下面列出每个键的作用:
Swap0:按Swap0,光标位置不变,将光标所在位置的数字与录入区的1号位置的数字(左起第一个数字)交换。如果光标已经处在录入区的1号位置,则按Swap0键之后,录入区的数字不变;
Swap1:按Swap1,光标位置不变,将光标所在位置的数字与录入区的6号位置的数字(左起第六个数字)交换。如果光标已经处在录入区的6号位置,则按Swap1键之后,录入区的数字不变;
Up:按Up,光标位置不变,将光标所在位置的数字加1(除非该数字是9)。例如,如果光标所在位置的数字为2,按Up之后,该处的数字变为3;如果该处数字为9,则按Up之后,数字不变,光标位置也不变;
Down:按Down,光标位置不变,将光标所在位置的数字减1(除非该数字是0),如果该处数字为0,则按Down之后,数字不变,光标位置也不变;
Left:按Left,光标左移一个位置,如果光标已经在录入区的1号位置(左起第一个位置)上,则光标不动;
Right:按Right,光标右移一个位置,如果光标已经在录入区的6号位置(左起第六个位置)上,则光标不动。
当然,为了使这样的键盘发挥作用,每次录入密码之前,录入区总会随机出现一个长度为6的初始密码,而且光标出现随机位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。
现在,阿兰有一个6位的数字密码,请编写一个程序,求出录入一个密码需要的最少的击键次数。
【输入文件】clever.in
两行,第一行为初始密码,空格后为光标位置(1-6),第二行为要输入的密码值。
【输出文件】clever.out
仅一行,为打出密码的最少击键次数。
【样例数据】
【输入】
123456 1
623453
【输出】
3
【参考程序1(盲目搜索)】
program clevertyper;
const
max=600000;
type
passtext=array[1..6] of byte; {用数组存储每一个密码数字}
tlist=record {结点类型}
father:longint;
dep:byte;
point:1..6;
state:passtext;
end;
var
source,target:passtext; {初始结点和目标结点}
list:array[0..max] of tlist; {扩展出的中间结点序列}
head,foot,best,i:longint;
answer:longint;
found:boolean;
str1:string[8];
point0:1..6;
procedure init; {初始化过程}
var
i:byte;
begin
assign(input,'clever.in');
reset(input);
assign(output,'clever.out');
rewrite(output);
readln(str1);
for i:=1 to 6 do
val(copy(str1,i,1),source[i]);
val(copy(str1,8,1),point0);
readln(str1);
for i:=1 to 6 do
val(copy(str1,i,1),target[i]);
fillchar(list,sizeof(list),0);
found:=false;
head:=0; {队列初始化,队首指针head,队尾指针foot}
foot:=1;
with list[1] do {初始结点作为队列第一个结点}
begin
state:=source;
dep:=0;
father:=0;
point:=point0;
end;
end;
function same(a,b:passtext):boolean;
var
i:byte;
begin
same:=false;
for i:=1 to 6 do
if a[i]<>b[i] then exit;
same:=true;
end;
function notappear(newv:tlist):boolean; {判断扩展出的结点是否已在队列中的函数}
var
i:longint;
begin
notappear:=false;
for i:=1 to foot do
if same(newv.state,list[i].state) and (newv.point=list[i].point)
then exit;
notappear:=true;
end;
procedure add(newv:tlist); {往队列中加入新结点过程}
begin
if notappear(newv)
then begin
inc(foot);
list[foot]:=newv;
end;
end;
procedure expand(index:longint;var n:tlist); {扩展结点过程}
var
i,x,y:integer;
newv:tlist;
begin
for i:=1 to 6 do {分别应用6条规则}
begin
if i=1 then
if n.point>1
then begin
newv.state:=n.state;
newv.point:=n.point;
newv.state[1]:=n.state[n.point];
newv.state[n.point]:=n.state[1];
end;
if i=2 then
if n.point<6
then begin
newv.state:=n.state;
newv.point:=n.point;
newv.state[6]:=n.state[n.point];
newv.state[n.point]:=n.state[6];
end;
if i=3 then
if n.state[n.point]<9
then begin
newv.state:=n.state;
newv.point:=n.point;
newv.state[n.point]:=newv.state[n.point]+1;
end;
if i=4 then
if n.state[n.point]>0
then begin
newv.state:=n.state;
newv.point:=n.point;
newv.state[n.point]:=newv.state[n.point]-1;
end;
if i=5 then
if n.point>1
then begin
newv.state:=n.state;
newv.point:=n.point-1;
end;
if i=6 then
if n.point<6
then begin
newv.state:=n.state;
newv.point:=n.point+1;
end;
newv.father:=index;
newv.dep:=n.dep+1;
add(newv);
end;
end;
procedure print(index:longint); {递归打印路径}
var
i,j:byte;
begin
if index=0 then exit;
print(list[index].father);
for i:=1 to 6 do
write(list[index].state[i]);
writeln(' ',list[index].point);
end;
begin{main}
init;
repeat
inc(head);
if same(list[head].state,target) {比较是否跟目标相同,相同则找到,否则扩展新结点}
then begin
found:=true;
best:=list[head].dep;
answer:=head;
break;
end;
if list[foot].dep>6 {搜索树的深度超过6时,速度很慢,显示超时}
then begin
writeln('OverTime!');
break;
end;
expand(head,list[head]);
until (head>=foot) or (foot>max) or found;
if found
then begin
writeln(best);
print(answer);
end
else writeln('No Answer');
close(input);
close(output);
end.
【参考程序2(结构优化)】
program clevertyper;
const
max=600000;
type
passtext=array[1..6] of byte; {用数组存储每一个密码数字}
tlist=record {结点类型}
step:byte;
point:1..6;
state:passtext;
end;
var
source,target:passtext; {初始结点和目标结点}
list:array[0..max] of tlist; {扩展出的中间结点序列}
app:array[1..6,0..9,0..9,0..9,0..9,0..9,0..9] of boolean;
head,foot:longint;
u,v,i:byte;
ch:char;
point0:1..6;
begin
assign(input,'clever.in');
reset(input);
for i:=1 to 6 do
begin
read(ch);
source[i]:=ord(ch)-48;
end;
read(ch);readln(point0);
for i:=1 to 6 do
begin
read(ch);
target[i]:=ord(ch)-48;
end;
close(input);
head:=0; {队列初始化,队首指针head,队尾指针foot}
foot:=1;
with list[1] do {初始结点作为队列第一个结点}
begin
state:=source;
step:=0;
point:=point0;
end;
fillchar(app,sizeof(app),false);
while true do
begin
head:=head+1;
with list[head] do
begin
if comparebyte(state,target,6)=0
then begin
assign(output,'clever.out');
rewrite(output);
writeln(step);
close(output);
break;
end;
{分别应用6条规则}
{按LEFT键}
if (point>1) and not app[point-1,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point-1;
app[point-1,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
{按RIGHT键}
if (point<6) and not app[point+1,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point+1;
app[point+1,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
{按DOWN键}
if state[point]>0
then begin
state[point]:=state[point]-1;
if not app[point,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point;
app[point,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
state[point]:=state[point]+1;{还原被扩展结点的值}
end;
{按UP键}
if state[point]<9
then begin
state[point]:=state[point]+1;
if not app[point,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point;
app[point,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
state[point]:=state[point]-1;{还原被扩展结点的值}
end;
{按swap0键}
u:=state[point];
v:=state[1];
state[1]:=u;
state[point]:=v;
if not app[point,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point;
app[point,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
{按swap1键}
state[1]:=v;
state[point]:=state[6];
state[6]:=u;
if not app[point,state[1],state[2],state[3],state[4],state[5],state[6]]
then begin
foot:=foot+1;
list[foot].state:=state;
list[foot].step:=step+1;
list[foot].point:=point;
app[point,state[1],state[2],state[3],state[4],state[5],state[6]]:=true;
end;
end;{with}
end;{while}
end.
浙公网安备 33010602011771号