SSL_2357
题目描述
有n个5*5的分区,每个为0或1,每次点中的分区以及这个分区上下左右改变(1变0,0变1),
求最少全变为1的次数。若次数大于6,则输出-1.
Sample Input
3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111
Sample Output
3
2
-1
数据范围
n<=500
解题思路
由全为1开始往前枚举,保存每个方阵的答案。
为了便于保存答案,每个方阵每行连接,变成25位的2进制数,用10进制值保存这个方阵。用位运算直接变换枚举。
如果未出现,加入队列,如果某一头指针变换次数>6或队列已经枚举完,结束搜索。
Source
const
p=34000000;
var
hash:array[0..p] of -1..6;
f,fa:array[1..500000] of longint;
n,m,l,i:longint;
function change(x,y:longint):longint;
begin
x:=x xor (1 shl y);
if (y mod 5<>0) then x:=x xor (1 shl (y-1));
if ((y+1) mod 5<>0) then x:=x xor (1 shl (y+1));
if (y>4) then x:=x xor (1 shl (y-5));
if (y<20) then x:=x xor (1 shl (y+5));
exit(x);
end;//自己和上下左右的0变1,1变0
procedure bfs;
var
head,tail,i:longint;
t,t1:longint;
begin
for i:=0 to p do hash[i]:=-1;
head:=0;
tail:=1;
f[1]:=1 shl 25-1;
hash[f[1]]:=0;
fa[1]:=0;
repeat
inc(head);
if hash[f[head]]>=6 then break;
for i:=0 to 24 do
begin
t:=change(f[head],i);
if hash[t]=-1 then
begin
if hash[f[head]]+1<=6 then
begin
inc(tail);
f[tail]:=t;
fa[tail]:=head;
hash[t]:=hash[f[head]]+1;
end;
end;
end;
until head>=tail;
end;
procedure init;
var
i,j,k:longint;
s:char;
begin
n:=0;
for i:=1 to 5 do
begin
for j:=1 to 5 do
begin
read(s);
k:=ord(s)-ord('0');
n:=n*2+k;
end;
readln;
end;
end;
begin
bfs;
readln(m);
for l:=1 to m do
begin
init;
writeln(hash[n]);
readln;
end;
end.
注意的地方
- hash表要开到2^25放答案
- 搜索的结束条件head>=tail一定要有=(wrong了无数遍的教训T_T)
- 空间和时间都要小心爆