USACO 3.2 Magic Squares 魔板 (BFS-HASH)

该博客探讨了USACO比赛中关于魔板的题目,通过描述题意和解决思路,指出可以通过'A'、'B'、'C'三种操作将初始矩阵变换到目标状态。作者提出使用广度优先搜索(BFS)配合哈希表来避免重复路径并高效地判断某个状态是否已访问过。

题意:

给定1234/换行/5678,用下面几种方法变到制定的数
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:中央四格作顺时针旋转。

思路:

可以发现他们三种之间有变化规律,然后就直接可以变过去。所以就一直bfs,如果以前找到的数找到过了,就不用这个节点了,在如何知道这个数有没有被找过就可以用hash来快速查找。

const
 maxn=1000007;
 rule:array [1..3,1..8] of longint=((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:array [0..maxn] of string[8];
 i,j,n,m,ans:longint;
 f,w,hash:array [1..maxn] of longint;


procedure init;
var
 i,j:longint;
 s:string;
begin
 s:='';
 for i:=1 to 8 do
  begin
   read(j);
   s:=s+chr(48+ord(j));
  end;
 state[0]:=s;
end;

function find(s:string):boolean;
var
 x,i,j:longint;
begin
 val(s,x);
 i:=x mod maxn;
 while (hash[i]<>x) and (hash[i]<>0) do i:=i mod maxn+1;
 if hash[i]=x then find:=true
              else find:=false;
 hash[i]:=x;
end;

procedure print(x:longint);
var
 i,j:longint;
begin
 if f[x]<>0 then
  begin
   inc(ans);
   print(f[x]);
  end;
 if f[x]=0 then writeln(ans) else
  if w[x]=1 then write('A')
   else if w[x]=2 then write('B')
    else if w[x]=3 then write('C');
end;


procedure bfs;
var
 i,j,tail,head:longint;
 flag:boolean;
begin
 state[1]:='12345678';
 hash[12345678 mod maxn]:=12345678;
 head:=0; tail:=1;
 if state[1]=state[0] then begin print(1); exit; end;
 repeat
  inc(head);
  for i:=1 to 3 do
  begin
   inc(tail);
   f[tail]:=head;
   w[tail]:=i;
   for j:=1 to 8 do
    state[tail]:=state[tail]+state[head,rule[i,j]];
   if find(state[tail])  then
   begin
    state[tail]:='';
    dec(tail);
   end;
   if state[tail]=state[0] then
   begin
    print(tail);
    exit;
   end;
  end;
 until tail<head;
end;


begin
 init;
 bfs;
end.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值