题目大意:
在成功地发明了魔方之后,拉比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:
1 2 3 4
8 7 6 5
我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。 这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。
下面是对基本状态进行操作的示范:
A: 8 7 6 5
1 2 3 4
B: 4 1 2 3
5 8 7 6
C: 1 7 2 4
8 6 3 5
对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。目标状态为八个数,a[i]表示第i位的目标状态。
基本状态必为12345678
所有整数范围均在1~8
题解:
广搜+hash:
这题的变化可以发现只有8!的情况总数,所以用hash判断当前搜的结果是否已经被遍历过,可以极大的优化时间,注意字符串的长度要限制,不要会炸内存= =
然后搜索有个预处理,你可以预判他每次操作以后,当前这个位置会被移到哪个位置,这时候开个rule表示当前数字做了i操作会被移到什么位置。
然后就是广搜= =深搜有很大可能栈溢出或者死循环到炸,所以不建议采取。
const
modn=1000007;
rule:array[1..3,1..8] of byte=((8,7,6,5,4,3,2,1),
(4,1,2,3,6,7,8,5),
(1,7,2,4,5,3,6,8));
var
state,hash:array [0..modn] of string[8];
f,w:array [0..modn] of longint;
i,x,ans:longint;
p,s:string;
function find(st:string):boolean;
var
i:longint;
begin
val(st,i);
i:=i mod modn;
while (hash[i]<>'') and (hash[i]<>st) and (i<modn) do inc(i);
if hash[i]=''
then begin hash[i]:=st; exit(false); end
else exit(true);
end;
procedure print(t:longint);
begin
if t=1 then exit;
inc(ans);
s:=chr(64+w[t])+s;
print(f[t]);
end;
procedure bfs;
var
head,tail,i,j:longint;
begin
head:=0; tail:=1;
w[1]:=0; f[1]:=0;
state[1]:='12345678';
if state[1]=p then exit;
repeat
inc(head);
for i:=1 to 3 do
begin
inc(tail);
f[tail]:=head;
w[tail]:=i;
state[tail]:=state[head];
for j:=1 to 8 do
state[tail,j]:=state[head,rule[i,j]];
if find(state[tail]) then dec(tail);
if state[tail]=p then
begin
print(tail);
tail:=0;
exit;
end;
end;
until head>=tail;
end;
begin
p:='';
for i:=1 to 8 do
begin
read(x);
p:=p+chr(48+ord(x));
end;
bfs;
writeln(ans);
writeln(s);
end.