您的位置:首页 > 其它

位运算简介及实用技巧(四):实战篇

2014-03-20 18:42 232 查看

下面分享的是我自己写的三个代码,里面有些题目也是我自己出的。这些代码都是在我的Pascal时代写的,恕不提供C语言了。代码写得并不好,我只是想告诉大家位运算在实战中的应用,包括了搜索和状态压缩DP方面的题目。其实大家可以在网上找到更多用位运算优化的题目,这里整理出一些自己写的代码,只是为了原创系列文章的完整性。这一系列文章到这里就结束了,希望大家能有所收获。

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;

var

total: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;

var

now: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;

var

p: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<MaxStep) then

begin

open:=open+1;

q[open].v:=update(q[close].v,p);

q[open].step:=q[close].step+1;

end;

until close>=open;

end;

procedure print(a:longint);

var

now: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;

var

ch: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 i<n then readln;

end;

end;

begin

solve;

main;

end.


======================= 性感的分割线 =======================

Problem : garden / 和MM逛花园

题目来源

07年Matrix67生日邀请赛第四题

问题描述

花园设计强调,简单就是美。Matrix67常去的花园有着非常简单的布局:花园的所有景点的位置都是“对齐”了的,这些景点可以看作是平面坐标上的格点。相邻的景点之间有小路相连,这些小路全部平行于坐标轴。景点和小路组成了一个“不完整的网格”。

一个典型的花园布局如左图所示。花园布局在6行4列的网格上,花园的16个景点的位置用红色标注在了图中。黑色线条表示景点间的小路,其余灰色部分实际并不存在。



Matrix67 的生日那天,他要带着他的MM在花园里游玩。Matrix67不会带MM两次经过同一个景点,因此每个景点最多被游览一次。他和他
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: