初始i=s

每次:i=(i-1) & s

直到i=0

etc.
11000
10000
01000
00000

10000=10001 & 11000
01000=01111 & 11000
00000=00111 & 11000

etc.
11110
11100
11010
11000
10110
10100
10010
10000
01110
01100
01010
01000
00110
00100
00010
00000

证明:
所有i满足 (s & i)==i,
且所有满足 (s & i)==i 的数都出现过

1.
证明:(s & i)==i
因为“i=(i’-1) & s”,

对于i的第t位i(t):

当s(t)=0时,i(t)=_ & 0 = 0
_ & 0 = 0

当s(t)=1时
1 & i(t) = i(t)

所以(s & i)==i成立

2.
证明:
所有满足 (s & i)==i 的数都出现过

对于s中值为0的位 s(t),因为“i=(i’-1) & s”,所以i(t)永远为0

对于s中值位0的位 s(t),因为“i=(i’-1) & s”,所以i(t)永远不会因为s而影响,所以i(t)的值 为(i’-1)的第t位

即“(s & i)==i”相当于原来s中的‘1’组成的数字从11…1到00…0每次减少1的变化,而原来s中的‘0’永远不变

得证

Usage:
共有n个人,当前有m个人可以工作,每个人可以被选或不被选,求出这m个人的所有选择情况(用二进制表示)

Problem:
hiho1516

bfs+状态压缩:

重要的是弄清每次生成新的状态的方法。。。

 #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> struct node
{
long pos,step,sum;
}q[];
//2^16 * 2(两岸) long n,cond[],g[],num[][];//0为起始岸;1为终止岸;2为船 总数(二进制)
long vis1[],vis2[],vis3;
bool vis[][]; bool judge()
{
long i,j,k;
for (j=;j<;j++)
{
for (i=;i<g[cond[j]];i++)
{
k=num[cond[j]][i];
if (((vis1[k] & cond[j])!=) && ((vis2[k] & cond[j])==))
return false;
} // for (i=0;i<n;i++)
// if (((cond[j]>>i) & i)!=1)
// if ( ((vis1[i] & cond[j])!=0) && ((vis2[i] & cond[j])==0) )
// return false;
}
if ((cond[] & vis3)==)
return false;
return true;
} int main()
{
long m,a,b,c,x,y,head,tail,i,j,k,total,pos,pos_,sum,step,mul[];
scanf("%ld%ld",&n,&m);
mul[]=;
for (i=;i<=n;i++)
mul[i]=mul[i-]<<;
total=(<<n)-;
for (i=;i<=total;i++)
{
g[i]=;
j=i;
k=;
while (j>)
{
if ((j & )==)
{
num[i][g[i]]=k;
g[i]++;
}
k++;
j=j>>;
}
} scanf("%ld%ld%ld",&a,&b,&c);
for (i=;i<n;i++)
{
vis1[i]=;
vis2[i]=;
}
vis3=;
for (i=;i<=a;i++)
{
scanf("%ld%ld",&x,&y);
vis1[x]+=<<y;
}
for (i=;i<=b;i++)
{
scanf("%ld%ld",&x,&y);
vis2[y]+=<<x;
}
for (i=;i<=c;i++)
{
scanf("%ld",&x);
vis3+=<<x;
}
for (i=;i<;i++)
for (j=;j<;j++)
vis[i][j]=true; head=;
tail=;
q[].pos=;
q[].step=;
q[].sum=total;
vis[total][]=false; while (head<tail)
{
head++; //另外的优化:
//如果在左边,则送尽量多的人到右边
//如果在右边,则送尽量少的人到左边 //编写程序的简单性:两岸做法的对称性 (Same),从而合二为一 pos=q[head].pos;
pos_=pos ^ ;
sum=q[head].sum;
step=q[head].step+;
//不必取0,前后必会发生变化
for (i=sum;i>;i=(i-) & sum)
if (g[i]<=m)
{
cond[]=i;
cond[pos]=sum-i;
cond[pos_]=total-cond[pos]; if (vis[cond[pos_]][pos_]==true && judge()==true)
{
// printf("%ld %ld\n",cond[pos_],pos_);
if (pos_== && cond[]==total)
{
printf("%ld\n",step);
return ;
}
tail++;
q[tail].pos=pos_;
q[tail].step=step;
q[tail].sum=cond[pos_];
vis[cond[pos_]][pos_]=false;
}
}
}
printf("-1\n");
return ;
}

/*

位运算的优势:
1.相比正常运算极快的运行速度
2.存储的减少
3.程序编写的简单(和不容易出错)

*/

位运算的一种应用 和 hiho1516过河解题报告的更多相关文章

  1. n&m位运算

    在C/C++语言里,&代表取地址或者“位与”运算 1.取变量的地址:&变量名,这将获得该变量的地址,例:int a = 1, &p = a. 2.进行位与运算,格式是:变量1& ...

  2. C语言位运算+实例讲解(转)

    按位或 按位与 按位异或 按位取反 左移右移 C语言位运算 有6种: &, | , ^(亦或), >(右移). 注意:参与位运算的元素必须是int型或者char型,以补码形式出现. 按位 ...

  3. js中的位运算

    按位运算符是把操作数看作一系列单独的位,而不是一个数字值.所以在这之前,不得不提到什么是"位": 数值或字符在内存内都是被存储为0和 1的序列,每个0和1被称之为1个位,比如说10 ...

  4. C#枚举中的位运算权限分配浅谈

    常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 & 0 = 0, 1 | 0 = 1, ~1 = 0 在设计权限时, 我们可以把权限管理操作转换为C#位运算来处理. 第 ...

  5. Java位运算经典实例

    一 源码.反码.补码 正数的源码.反码.补码相同,例如5:            5的源码:101            5的反码:101            5的补码:101 负数的源码.反码.补 ...

  6. EF架构~为分组添加位运算聚合方法

    回到目录 我们知道在Linq里的分组groupby可以对集合中一个或者多个字段进行分组,并对其中一个属性进行聚合,而Linq为我们提供了多种聚合方法,由aver,sum,count等,而在大叔权限体系 ...

  7. leetcode - 位运算题目汇总(下)

    接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...

  8. 深入理解计算机系统(2.2)---布尔代数以及C语言上的位运算

    布尔代数上的位运算 布尔代数是一个数学知识体系,它在0和1的二进制值上演化而来的. 我们不需要去彻底的了解这个知识体系,但是里面定义了几种二进制的运算,却是我们在平时的编程过程当中也会遇到的.这四种运 ...

  9. 关于PHP位运算的简单权限设计

    写在最前面 最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务.关于二进制数 的位运算,常见的就是“或.与.非”这三种简单运算了,当然,我也查看了下PHP手册 ...

随机推荐

  1. 课程设计个人报告——基于ARM实验箱的Android交友软件的设计与实现

    个人贡献 熟悉试验箱各元件功能以及连接组装试验箱 一.实验内容 研究实验箱串口.USB线的调通连接 二.实践步骤 1.打开实验箱,首先了解各元件功能 这个是LTE模块,也叫4G模块,具体的作用是硬件将 ...

  2. Getting Start chrome-extension demo

    写一个小小的chrome扩展demo~ 准备工作 了解一下插件chrome-extension: 在应用商店里的插件基本上都是以.crx为文件后缀,该文件其实就是一个压缩包,包括插件所需要的html. ...

  3. MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”

    问题 MSBUILD : error MSB3428: 未能加载 Visual C++ 组件"VCBuild.exe".要解决此问题,1) 安装 .NET Framework 2. ...

  4. Spring MVC统一异常处理

    实际上Spring MVC处理异常有3种方式: (1)一种是在Controller类内部使用@ExceptionHandler使用注解实现异常处理: 可以在Controller内部实现更个性化点异常处 ...

  5. javascript典型bug——错误的闭包

    昨天QT给我的一个功能提了一个bug.大概意思就是说,一段在不同位置都会被调用的代码,在A处被调用的时候,似乎会对其他调用的地方产生影响. 我仔细debug了半天,终于找到了原因.简化过的代码如下: ...

  6. Asp.Net_序列化、反序列化

    .net序列化及反序列化 在我们深入探讨C#序列化和反序列化之前我们先要明白什么是序列化,它又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.序列化就是把一个对象保存到一个文件或数据库 ...

  7. 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1

    摘要: 全球开源区块链领域影响最为广泛的Hyperledger Fabric日前宣布了1.1版本的正式发布,带来了一系列丰富的新功能以及在安全性.性能与扩展性等方面的显著提升.阿里云容器服务区块链解决 ...

  8. App推荐 | Google Tasks

    前不久,Google推出了一款移动任务管理应用Google Task,在使用2天后,写一下使用感受,并与Google同类产品Keep进行一个对比. 首先欣赏几张官方的App截图 然后来看一下官方的介绍 ...

  9. 20135119_涂文斌 实验三 敏捷开发与XP实践

    北京电子科技学院(BESTI) 实  验  报  告 课程: Java        班级:1351           姓名:涂文斌          学号:20135119 成绩:         ...

  10. PHP的魔术方法

    PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods) 魔术方法包括: __construct(),类的构造函数 __destruct(),类的析构函数 __call(),在对 ...