位運算簡介及實用技巧(四) 實戰篇

2021-06-21 02:40:01 字數 3488 閱讀 7528

matrix67原創,轉貼請註明出處。

problem : 費解的開關

題目**

06年noip模擬賽(一) by matrix67 第四題

問題描述

你玩過「拉燈」遊戲嗎?25盞燈排成乙個5×5的方形。每乙個燈都有乙個開關,遊戲者可以改變它的狀態。每一步,遊戲者可以改變某乙個燈的狀態。遊戲者改變乙個燈的狀態會產生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態。

我們用數字「1」表示一盞開著的燈,用數字「0」表示關著的燈。下面這種狀態

10111

01101

10111

10000

11011

在改變了最左上角的燈的狀態後將變成:

01111

11101

10111

10000

11011

再改變它正中間的燈後狀態將變成:

01111

11001

11001

10100

11011

給定一些遊戲的初始狀態,編寫程式判斷遊戲者是否可能在6步以內使所有的燈都變亮。

輸入格式

第一行有乙個正整數n,代表資料中共有n個待解決的遊戲初始狀態。

以下若干行資料分為n組,每組資料有5行,每行5個字元。每組資料描述了乙個遊戲的初始狀態。各組資料間用乙個空行分隔。

對於30%的資料,n<=5;

對於100%的資料,n<=500。

輸出格式

輸出資料一共有n行,每行有乙個小於等於6的整數,它表示對於輸入資料中對應的遊戲狀態最少需要幾步才能使所有燈變亮。

對於某乙個遊戲初始狀態,若6步以內無法使所有燈變亮,請輸出「-1」。

樣例輸入 3

00111

01011

10001

11010

11100

11101

11101

11110

11111

11111

01111

11111

11111

11111

11111

樣例輸出 3

2-1

程式**

const

bigprime=3214567;

maxstep=6;

type

pointer=^rec;

rec=record

v:longint;

step:integer;

next:pointer;

end;

vartotal:longint;

hash:array[0..bigprime-1]of pointer;

q:array[1..400000]of rec;

function update(a:longint;p:integer):longint;

begin

a:=a xor (1 shl p);

if p mod 5<>0 then a:=a xor (1 shl (p-1));

if (p+1) mod 5<>0 then a:=a xor (1 shl (p+1));

if p<20 then a:=a xor (1 shl (p+5));

if p>4 then a:=a xor (1 shl (p-5));

exit(a);

end;

function find(a:longint;step:integer):boolean;

varnow:pointer;

begin

now:=hash[a mod bigprime];

while now<>nil do

begin

if now^.v=a then exit(true);

now:=now^.next;

end;

new(now);

now^.v:=a;

now^.step:=step;

now^.next:=hash[a mod bigprime];

hash[a mod bigprime]:=now;

total:=total+1;

exit(false);

end;

procedure solve;

varp:integer;

close:longint=0;

open:longint=1;

begin

find(1 shl 25-1,0);

q[1].v:=1 shl 25-1;

q[1].step:=0;

repeat

inc(close);

for p:=0 to 24 do

if not find(update(q[close].v,p),q[close].step+1) and (q[close].step+1=open;

end;

procedure print(a:longint);

varnow:pointer;

begin

now:=hash[a mod bigprime];

while now<>nil do

begin

if now^.v=a then

begin

writeln(now^.step);

exit;

end;

now:=now^.next;

end;

writeln(-1);

end;

procedure main;

varch:char;

i,j,n:integer;

t:longint;

begin

readln(n);

for i:=1 to n do

begin

t:=0;

for j:=1 to 25 do

begin

read(ch);

t:=t*2+ord(ch)-48;

if j mod 5=0 then readln;

end;

print(t);

if i07年matrix67生日邀請賽第四題

問題描述

花園設計強調,簡單就是美。matrix67常去的花園有著非常簡單的布局:花園的所有景點的位置都是「對齊」了的,這些景點可以看作是平面座標上的格點。相鄰的景點之間有小路相連,這些小路全部平行於座標軸。景點和小路組成了乙個「不完整的網格」。

乙個典型的花園布局如左圖所示。花園布局在6行4列的網格上,花園的16個景點的位置用紅色標註在了圖中。黑色線條表示景點間的小路,其餘灰色部分實際並不存在。

matrix67 的生日那天,他要帶著他的mm在花園裡遊玩。matrix67不會帶mm兩次經過同乙個景點,因此每個景點最多被遊覽一次。他和他

位運算簡介及實用技巧(一) 基礎篇

去年年底寫的關於位運算的日誌是這個blog裡少數大受歡迎的文章之一,很多人都希望我能不斷完善那篇文章。後來我看到了不少其它的資料,學習到了更多關於位運算的知識,有了重新整理位運算技巧的想法。從今天起我就開始寫這一系列位運算講解文章,與其說是原來那篇文章的follow up,不如說是乙個remake。...

位運算簡介及實用技巧(一) 基礎篇

轉於http www.matrix67.com blog archives 263 去年年底寫的關於位運算的日誌是這個blog裡少數大受歡迎的文章之一,很多人都希望我能不斷完善那篇文章。後來我看到了不少其它的資料,學習到了更多關於位運算的知識,有了重新整理位運算技巧的想法。從今天起我就開始寫這一系列...

位運算簡介及實用技巧(一) 基礎篇

什麼是位運算?程式中的所有數在計算機記憶體中都是以二進位制的形式儲存的。位運算說穿了,就是直接對整 數在記憶體中的二進位制位進行操作。比如,and運算本來是乙個邏輯運算子,但整數與整數之間也可以進行and運算。舉個例子,6的二進位制是110,11的二 進製是1011,那麼6 and 11的結果就是2...