<<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数,| 运算符表示对2个数的二进制位进行比较,只要2个之中有一个这个位是1,则2者进行或运算之后得到的那个二进制数相应的位也是1。

因此,可以将3个数进行左移操作,然后再进行或运算,最后得到一个数,然后就可以通过这个数进行右移操作再进行&0xff操作就能得到原来的数。由于直接对二进制进行操作,因而速度极快。

有读者可能会说可以直接开一个结构体,将3个数都归属于一个结构体中,这样当然可以,不过速度远慢于上述操作。

对于POJ3523---The Morning after Halloween(UVa 1601)题目,运用结构体的运行时间是4672MS,而用第一个方法的运行时间是3719MS。所以明显第一个方法远远优于结构体方法。

以下为题目完整代码:

///本题可以通过对空白格进行构图,从而减少广搜时所需的操作时间。可以对每个空格进行编号,然后记录开始状态和结束状态,从开始状态对图进行广搜

#include<cstdio>
#include<queue>
#include<cstring>
#include<cctype>
using namespace std; const int maxs=;
const int maxn=;
const int dr[]= {,-,,,}; /// 4 moves, plus "no move"
const int dc[]= {,,,-,}; inline int ID(int a, int b, int c)
{
return (a<<)|(b<<)|c;///由于int 类型保存8个字节,所以这个操作将a放到了最前面的8个字节,b放到了中间的8个字节,c放到了最后的8个字节
} int s[],t[];///s表示开始位置,t表示终点位置
int degree[maxn],G[maxn][];
inline bool conflict(int a, int b, int a2, int b2)
{
return a2 == b2 || (a2 == b && b2 == a);///第一个表示a,b进入同一空格,第二个表示2者交换位置
}
int d[maxn][maxn][maxn];///表示所走的总步数 int bfs()
{
queue<int> q;
q.push(ID(s[],s[],s[]));
memset(d,-,sizeof(d));
d[s[]][s[]][s[]]=;
while(!q.empty())
{
int u=q.front();
q.pop();
int a=(u>>)&0xff,b=(u>>)&0xff,c=u&0xff;
if(a==t[]&&b==t[]&&c==t[]) return d[a][b][c];
for(int i=;i<degree[a];i++)///从第一个鬼开始,查找连通的空格
{
int a2=G[a][i];
for(int j=;j<degree[b];j++)
{
int b2=G[b][j];
if(conflict(a,b,a2,b2)) continue;
for(int k=;k<degree[c];k++)
{
int c2=G[c][k];
if(conflict(a, c, a2, c2)) continue;
if(conflict(b, c, b2, c2)) continue;
if(d[a2][b2][c2]!=-) continue;///判断是否被访问过
d[a2][b2][c2]=d[a][b][c]+;
q.push(ID(a2,b2,c2));
}
}
}
}
return -;
} int main()
{
int w,h,n;
while(~scanf("%d%d%d\n",&w,&h,&n)&&w)
{
char maze[][];
for(int i = ; i < h; i++)
fgets(maze[i], , stdin); int cnt,x[maxn],y[maxn],id[maxs][maxs];///cnt 用于计数,id数组用于记录空格所处位置及其编号
cnt=;
for(int i=; i<h; i++)
for(int j=; j<w; j++)
if(maze[i][j]!='#')
{
x[cnt]=i;
y[cnt]=j;
id[i][j]=cnt;
if(islower(maze[i][j])) s[maze[i][j]-'a']=cnt;
else if(isupper(maze[i][j])) t[maze[i][j]-'A']=cnt;
cnt++;
} for(int i=; i<cnt; i++) ///建图
{
degree[i]=;
for(int dir=; dir<; dir++)
{
int nx=x[i]+dr[dir];
int ny=y[i]+dc[dir];
if(maze[nx][ny]!='#') G[i][degree[i]++]=id[nx][ny];
}
}
///加入假鬼,使3种情况都能按照3个鬼的bfs进行,由于假鬼开始就待在终点,所以不会对结果产生影响
if(n <= )
{
degree[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
}
if(n <= )
{
degree[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
}
printf("%d\n",bfs());
}
return ;
}

<<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Linux c++ time different

    下面这个函数可以得到微秒级别: #include<time.h> int clock_gettime(clockid_t clk_id,struct timespec *tp); 函数&q ...

  2. java ArrayList 迭代器快速失败源码分析

    先来看一个例子: @Test void test2() { ArrayList<String> list = new ArrayList<String>(); list.add ...

  3. laravel中当使用Elquent ORM中的模型作为参数进行传递时的方法:

    Controller中的函数: /* $modelArg:是调用模型的路径,以字符串的形式传递过来. $id:要查询当前模型的id号. $args:具体查询的字段 */ public function ...

  4. JavaBean理解

    Java语言欠缺属性.事件.多重继承功能.所以,如果要在Java程序中实现一些面向对象编程的常见需求,只能手写大量胶水代码.Java Bean正是编写这套胶水代码的惯用模式或约定.这些约定包括getX ...

  5. Linux系统默默改变了人类世界的生活方式

    你知道操作系统都有些什么吗?Windows啊.这是我在上大学之前的问答,我当时认为只一种叫做Windows的操作系统,可是我错了,当我上大学以后,作为计算机专业的一名学生的时候我第一次接触到了除Win ...

  6. AttributeError: 'cx_Oracle.Cursor' object has no attribute 'numbersAsStrings'

    转载自:https://www.wengbi.com/thread_77579_1.html 最近在本地搭建Django开发环境,Django 1.11,python 2.7.11,数据库Oracle ...

  7. RTTI,C++类型转换操作符

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  8. 【转载二】Grafana系列教程–Grafana的下载及安装

    本篇教程,waitig 来为大家介绍一下Grafana的安装及运行的方式. 更多Grafana技术请加入<InfluxDB&Grafana技术交流群:580487672(点击加入)> ...

  9. 从mysql读取数据写入mongo

    # coding:utf-8 # Created by qinlin.liu at 2017/3/14 import pymysql import datetime #pymongo说明文档  : h ...

  10. ubuntu查看占用某端口的程序

    查看端口使用情况,使用netstat命令. 查看已经连接的服务端口(ESTABLISHED netstat -a 查看所有的服务端口(LISTEN,ESTABLISHED) netstat -ap 查 ...