acm位运算应用 搜索

搜索
 
  此处不讲题目,只讲位运算是怎样在这些题中实现和应用的。由于搜索题往往是基于对状态的操作,位运算往往特别有效,优化之后的效果可以有目共睹。
 
  例1、POJ 1324
 
  根据题目,确定了对状态的表示之后(记录当前状态的蛇头x, y值与剩下部分的运动状态),一般容易想到剩下部分的运动状态用一个数组(比如x[n-1], n为蛇节点数,n[0]为第二个节点的运动趋势)去表示,且一个数组元素的值为0,1,2,3,即四个方向,蛇每次移动,这个方向数组需要更新一次,更新是很简单的,除了n[0]更新之外,剩下的 n等于上一轮的n[i-1](i>1);如果用数组,就必须用一个循环去更新它,这样会导致程序速度不是很理想,所以可以想到用位运算去模拟,简言之,就是把原来的一个数组压缩的一个变量上去存储,原来任何一个数组元素的值范围0~3, 用二进制表示就是 00 ~ 11,最多占用2位,这样,我们就可以通过移位运算,和或运算去实现所以操作。
 
  基本技巧: 如果给你个一个方向序列   a0, a1, a2, a3, .... a(n-1),放到变量b中,且以最低位表示an,可以用如下循环
 
  b = 0;
 
  for(i=0; i<n; i++)
 
       b = (b<<2) | a;
 
  即,每次把已经处理好的位段向上移两位,这样,在低位就会自动补齐两个0,用一个 | 操作,就吧新的值给放进变量中了。
 
  如果要从b中复原,则可使用 >> 的办法
 
  for(i=0; i<n; i++)
 
         a[n-1-i] = (b >> (i*2)) & 3;
 
  移位会将低位元素除掉,而 & 3则是把移到低位的元素取出。
 
  更高效的方法是(两种方法的前提都是不改变b的值)
 
  t = b;
 
  for(i=0; i<n; i++){
 
      a[n-1-i] = t & 3;
 
      t >>= 2;
 
  }
 
  高效的原因如帖子开头所述。
 
  在表示状态的位段操作中,最好将变量设为unsigned int (short)型,因为有符号型(负数的最高位(符号位)为1)的 >>操作加在负数上时会在右边引入1而不是0, 这基本上不会是你想要的操作。
 
  例2、POJ 3460 Booksort
 
  这题可以在对书进行交换的时候应用位运算,也许你认为用数组去模拟更为直观,但是看看下面的实现,也许你就不那么认为了。
 
  书最大编号15,
 
  这样就开一个64位整形,每4位表示一本书
 
  首先预处理,计算出两张表
 
  extract[j] 和 clear[j]分别表示把书架上第i到j本书取出或清空,显然在i到j一段,位上全是1,而其他部分是0,而clear[j]就是extract[j]的取反
 
  计算方法如下:
 
  typedef unsigned long long longint;
 
  const longint base = 15;//这是必须注意的,普通的常数15是整形,在以下的操作中会越界
 
  for (i = 0; i < 15; i++) {
 
     extract = base << (i * 4);
 
     clear = ~extract;
 
     for (j = i + 1; j < 15; j++) {
 
      extract[j] = extract[j-1] | (base << (j * 4));
 
      clear[j] = ~extract[j];
 
     }
 
  }
 
  计算出这些以后,交换书就变得异常简单
 
  inline void transposition(longint &cur, longint &next, int &i,   int &k, int &j) {//i,k段与k+1,c段置换
 
  next = cur & clear[j];
 
  next |= (cur & extract[k]) << ((j - k) << 2);
 
  next |= (cur & extract[k+1][j]) >> ((k - i + 1) << 2);
 
  }
 
  先把i到j全部清空后的值赋给next,把 i, k段的书取出,移到高位(差值为(j - k) * 4),同理,再把k+i到j段的值取出移到低位。
 
  如此清楚明了,而如果用数组的话,10+行的语句是少不了的,而且容易搞错。
 
  例3:HOJ 八数码问题
 
  http://acm.hnu.cn:8080/online/?action=problem&type=show&id=10466
 
  这题用位运算我倒是没有达到更快,空间稍微节省了些。
 
  另外,这题的测试数据很强的说,赞一个。
 
  用64位的整形去表示整个状态,其中每4位表示一个数码(0~8),如果是用char数组,则用9个,用了72位。
 
  取出某一位和清空某一位的掩码事先要计算好
 
  这样做比用一个整形数如 123480567 之类的去表示更有优势,因为显然取出某一位的速度非常快,不需要 % 10, /10之类耗时的操作,如果这样实现的话就不要用stl的map了,我无聊地试了次,相当之慢。还是老老实实康托展开的好。不过和开char数组的速度差不多的说(虽然说赋值时间大了,但毕竟别人是数组,呵呵,要是有每4位做一个单位的数组就好了——不要跟我说用struct里面定义的位段啊,那相当的慢)。
 
  最近还做了一个POJ 2286,可以用位运算,但貌似有些麻烦,没用,结果被一个用pascal的小子超在前面,哪天状态好了要把这题改用位运算去做,就不信刷不到   0ms.

acm位运算应用 搜索的更多相关文章

  1. ACM位运算技巧

    ACM位运算技巧 位运算应用口位运算应用口诀位运算应用口诀 清零取反要用与,某位置一可用或 若要取反和交换,轻轻松松用异或 移位运算 要点 1 它们都是双目运算符,两个运算分量都是整形,结果也是整形. ...

  2. ACM 位运算

    的幂 boolean power2(int x) { return((x&(x-1))==0)&&(x!=0): } For example: #include<stdi ...

  3. ACM中的位运算技巧

    听说位运算挺好玩的,那这节总结一下ACM中可能用到的位运算技巧. XOR运算极为重要!!(过[LC136](只出现一次的数字 - 力扣(LeetCode)):数组中每个数字都出现两次,只有一个出现一次 ...

  4. [位运算] [搜索] [递推优化] [计算几何] TEST 2016.7.15

    NOIP2014 提高组模拟试题 第一试试题 题目概况: 中文题目名称 合理种植 排队 科技节 源程序文件名 plant.pas/.c/.cpp lineup.pas/.c/.cpp scifest. ...

  5. [CODEVS1295]N皇后(位运算+搜索)

    题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任 ...

  6. [POJ2965]The Pilots Brothers' refrigerator (搜索/位运算)

    题意 游戏“The Pilots Brothers:跟随有条纹的大象”有一个玩家需要打开冰箱的任务. 冰箱门上有16个把手.每个手柄可以处于以下两种状态之一:打开或关闭.只有当所有把手都打开时,冰箱才 ...

  7. POJ 3220 位运算+搜索

    转载自:http://blog.csdn.net/lyhypacm/article/details/5813634 DES:相邻的两盏灯状态可以互换,给出初始状态.询问是否能在三步之内到达.如果能的话 ...

  8. AndyQsmart ACM学习历程——ZOJ3870 Team Formation(位运算)

    Description For an upcoming programming contest, Edward, the headmaster of Marjar University, is for ...

  9. 你必须知道的基本位运算技巧(状压DP、搜索优化都会用到)

    一. 位操作基础 基本的位操作符有与.或.异或.取反.左移.右移这6种,它们的运算规则如下所示: 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两个位都为0时,结果才为0 ...

随机推荐

  1. thinkphp分页实现

    以上为我对于thinkphp分页的实现效果,两种方法,一种调用公共函数中的函数方法(参考http://www.cnblogs.com/tianguook/p/4326613.html),一种是在模型中 ...

  2. call_user_func_array

    call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数 参数 callback 被调用的回调函数. param_arr 要被传入回调函数的数组,这个数组得是索引 ...

  3. linux管道的容量和内部组织方式

    1.管道容量  count=65536,即64KB #include<stdio.h> #include<sys/types.h> #include<unistd.h&g ...

  4. E8.NET工作流平台如何与其他软件系统集成?

    1.与邮件系统集成 E8.Net工作流开发架构已经提供了与电子邮件系统集成的模块,可以轻松实现与EXCHANGE等专业邮件系统集成的应用需求. 2.与短信系统集成 E8.Net工作流架构已经提供了手机 ...

  5. C# zip/unzip with DotNet framework 4.5

    add reference System.IO.Compression.FileSystem public class ZipHelper { public static string UnZip(s ...

  6. javascript 闭包暴露句柄和命名冲突的解决方案

    暴露 最近在琢磨前端Js开源项目的东西,然后就一直好奇他们是怎么句柄暴露出来的,特整理一下两种方法. 将对象悬挂到window下面. 不使用var进行变量声明.下面上代码: (function(win ...

  7. Oracle数据库的下载和安装

    那天分享一下Oracle的下载和安装的过程,有需要的朋友可以借鉴参考一下.如有雷同不胜感激! 首先可以到Oracle的官网下载Oracle的最次年版本的Oracle数据库.一下是个人下载的数据库版本百 ...

  8. bzoj 2406: 矩阵 上下界网络流判定

    2406: 矩阵 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 138  Solved: 46[Submit][Status][Discuss] De ...

  9. 基于协同过滤的个性化Web推荐

    下面这是论文笔记,其实主要是摘抄,这片博士论文很有逻辑性,层层深入,所以笔者保留的比较多. 看到第二章,我发现其实这片文章对我来说更多是科普,科普吧…… 一.论文来源 Personalized Web ...

  10. SQL中Case的使用方法(下篇)(转)

    接上篇 四,根据条件有选择的UPDATE. 例,有如下更新条件 工资5000以上的职员,工资减少10% 工资在2000到4600之间的职员,工资增加15% 很容易考虑的是选择执行两次UPDATE语句, ...