初始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. 2017-2018-2 《网络对抗技术》 20155302 第二周 Exp1 PC平台逆向破解(5)M

    2017-2018-2 <网络对抗技术> 20155302 第二周 Exp1 PC平台逆向破解(5)M 1-实践目标 1.1-实践介绍 本次实践的对象是一个名为pwn1的linux可执行文 ...

  2. 20155311《网络对抗》Web安全基础实践

    20155311<网络对抗>Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御? 原理:SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL ...

  3. mfc CFileFind查找类

    查找文件 CFileFind类 提取文件图标 显示大图标 显示小图标 一.查找文件 . CFileFind类 //c:\mydir\myfile.txt GetFileName 获取文件名 myfil ...

  4. 【LG4248】[AHOI2013]差异

    [LG4248][AHOI2013]差异 题面 洛谷 题解 后缀数组版做法戳我 我们将原串\(reverse\),根据后缀自动机的性质,两个后缀的\(lcp\)一定是我们在反串后两个前缀的\(lca\ ...

  5. 页面添加友盟(CNZZ)统计和事件追踪

    1. 在页面中引入友盟(CNZZ)统计的 JS 代码 <script type="text/javascript"> // 统计 var cnzz_protocol = ...

  6. Jmeter(二十三)_插件扩展

    Jmeter插件管理器 安装插件的方法有两种,一种是传统的方式,即官网下载,本地配置,重启jmeter.现在有一种快捷的方法可以自定义安装插件-插件管理器 JMeter 插件管理器的使用方法很简单:不 ...

  7. 通过Mysql连接ASP.Net Core2.0(Code First模式)

    ASP.NET Core2.0连接Mysql,首先新建项目 选择Web应用程序 选择需要身份验证: 通过Nuget安装Mysql驱动,这里推荐>Pomelo.EntityFrameworkCor ...

  8. Docker操作命令

    docker --直接输入 docker 命令来查看到 Docker 客户端的所有命令选项. docker [command] --help --深入的了解指定的 Docker 命令使用方法 dock ...

  9. mysql select 字段别名是否可以用在 select中或者where中

    select column1+10 as c1,c1+10 as c2 from table1;想实现上面的效果,结果在mysql里面报错了,提示找不到c1这个列; -- 不同的 数据库不一样 一般不 ...

  10. Android中应用contentprovider来创建数据库的一些步骤

    http://blog.csdn.net/xiaodongvtion/article/details/7865669 1:首先创建一个xxprovider的class,它是extendscontent ...