SSL_2357 位运算

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)
  • 空间和时间都要小心爆
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值