SSL_2357 位运算

来源:互联网 发布:天敏网络电视机顶盒 编辑:程序博客网 时间:2024/04/27 16:27

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变0procedure 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)
  • 空间和时间都要小心爆
0 0
原创粉丝点击