二进制<4>

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

下面分享的是我自己写的三个代码,里面有些题目也是我自己出的。这些代码都是在我的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两次经过同一个景点,因此每个景点最多被游览一次。他和他

时间: 2024-10-13 22:52:25

二进制<4>的相关文章

python中 将你的名字转化成为二进制并输出

1 name = "吴彦祖" 2 for i in name: 3 i_by = bytes(i, encoding = "utf-8") 4 for i_bin in i_by: 5 i_b = bin(i_bin) 6 print(i_b) 输出结果: 0b10110100 0b10100110 0b10010110 我们来详细解读每个转换步骤:for i in name: 通过for循环获取所有的字符i,共获取了3个字符 i_by = bytes(i, enc

JavaScript 二进制的 AST

本文和大家分享的主要是javascript中二进制的 AST相关内容,一起来看看吧,希望对大家学习javascript有所帮助. 背景介绍 多年来,JavaScript 已经从最慢的脚本语言之一,从老爷车发展为兰博基尼,不管是通过 Web 浏览器还是其他环境.它都能够快到可以运行桌面.服务器.移动甚至嵌入式应用程序. 随着 JavaScript 的增长,应用程序的复杂程度和规模都越来越复杂.然而,二十年前,少数使用过 JavaScript 的网站也就加载几千字节的 JavaScript,许多网站

二进制

题目链接:here 对于 n 瓶一升的水,把他们合并后,最少需要的瓶子数为 n 的二进制中 1 的个数.假 设 n 的二进制中 1 的个数大于 k,那么我们要找到 1 个大于 n 的数,且二进制中 1 的个数等 于 k 的最小的数 m,那么答案为 m-n. 假设 n 二进制中,最右边的 1 在第 i 位(这里的第几位是从右往左数的,最右边为第 0 位),那么假设你加上一个小于 2^i 的数,结果二进制中 1 的个数只会增加,如果加上一个 2^i,则结果二进制中 1 的个数必定不会增加.所以只需要

判断给定十进制整数的二进制形式中含有几个1

两种判断一个给定整数的二进制形式中含有几个1的简单方法: 主要思想是通过按位与(&)运算和位移运算(<< >>)实现 1 unsigned int_number( int n) 2 { 3 if (n < 0) 4 return; 5 unsigned count = 0; 6 while (n != 0) 7 { 8 if ((n & 1) != 0) 9 ++count; 10 n >>= 1; 11 } 12 return count; 13

二进制思惟以及数据的存储

我们平常运用的数字多是由 0~9 共十个数字构成的,例如 1.9.10.297.952 等,一个数字最多能表现九,假如要表现十.十一.二十九.一百等,就需求多个数字组合起来.例如表现 5+8 的后果,一个数字不敷,只能"进位",用 13 来表现:这时"进一位"相当于十,"进两位"相当于二十.由于逢十进一,也由于只要 0~9 共十个数字,所以叫做十进制(Decimalism).进制也就是进位制.在停止加法(减法)运算时,逢X进(借)一就是X进制,这

使用C#向Sql Sever中存取网络图片和本地图片(二进制流的形式)

先是做普通的,存储我们本地的图片,将它转化为二进制流存储到数据库对应的表中. 代码如下: string path = "../../A.jpg"; FileStream fs = new FileStream(path, FileMode.Open); int streamLength = (int)fs.Length; //获取文件流的长度. byte[] image = new byte[streamLength]; //声明字节数组,用于保存图片文件 fs.Read(image,

centos6.5二进制安装mysql

[[email protected] ~]# yum install libaio-devel -y    #安装共享库 [[email protected] ~]# wget http://mirrors.sohu.com/mysql/My ... ux2.6-x86_64.tar.gz #下载MySQL二进制包 [[email protected] ~]# tar xf mysql-5.5.48-linux2.6-x86_64.tar.gz #解压二进制包 [[email protected

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

mariadb通用二进制格式安装

一.MariaDB安装介绍: 对于通用二进制格式的包,我们只需要解压缩后就能够使用数据库,听起来很容易,但必须要注意一些问题.二进制 格式的程序包是已经编译好的二进制程序,所以里边有很多脚本都是在固定的路径下执行的,所以安装过程中mysql这个路径必须安装在/usr/local目录下,并且目录名称必须叫mysql.如果不这样设置,一些脚本无法运行,更别提能成功安装了. Mariadb通用二进制格式相关文件说明 当获取到Mariadb通用二进制格式文件,解压后查看其文件如下:     [[emai

二进制文件文本文件和二进制数据

我们知道计算机是用二进制来做运算处理的,所以所有存储在计算机里面的东西都是二进制的. 我也知道这句话,但为什么总是听到别人说"二进制"文件和"文本"文件呢? 按照上面那句话来说计算机里面的都应该是二进制的啊! 底层存储的都是二进制的"数据",而不是二进制的文件. 列举一个二进制文件如下: 00000000h:0F 01 00 00 0F 03 00 00 12 53 21 45 58 62 35 34; .........S!EXb54 0000