二进制优化(数独问题+有向图问题)

【】众所周知啊,在遇见一个数独怪兽的时候,想要打败它就必须将它的空白部分全部填完,而对于每一个空白格子呢,我们既要看它的所属行还有哪些可以填入的数字,又要看的所属列还有哪些可填的数字,不仅如此啊,还有看它的所属宫格还有哪些可填的数字,简直是不胜其烦啊(我裂开了啊)!!!!这时候呢,大部分小伙伴呢就会想到说:这有啥啊,不就是是三个bool数组加上两个&&就可以的事情吗。这样纵然可以实现,但还有没有更加炫酷,啊呸,实用又快速的方法呢,答案当然是有滴(又掉了几根,好心疼!!)

【】今天,我们就来看看这神奇的二进制优化!!!

【】给你这样一个数独要你填写剩下的空白格子

                                   

这样,我么先定义行数组row[9], 列数组col[9], 宫数组cell[3][3],并且全部初始化为512-1(二进制表示为0000 0000 1111 1111)  当然如果会使用bitset容器的话,下面的操作会更简单,

就拿第二行第一列(2,1)来说话吧 

第二行
0 0 2 1 0 9 4 0 0
row[1]对应二进制表示
0 1 1 1 1 0 1 0 0

第一列
1 0 0 3 0 7 0 0 8
col[0]对应二进制表示
1 0 0 1 1 1 0 1 0

扫描二维码关注公众号,回复: 14759928 查看本文章
第一宫
1 0 3
0 0 2
0 0 0
cell[0][0]对应二进制表示
1 1 1 1 1 1 0 0 0

【对应方式】在所属行/列/宫中出现过的数字n在对应的行/列/宫的的数字的二进制要表示为0,表示该行所有空格都不能再填这个数字n (例如:第二行中已经有了数字9,所以row[1]的二进制表示的第9位(从右到左)要改为0,表示不能使用,而该行中没有出现过数字3,所以第三位还是为1,不改动),

【】经过这样的一番操作后呢,我们要求出还有哪些可以填入(2,1)的数字就可以通过对row[1],col[0],cell[0][0]求交集就可以啦,即int index=row[1]&col[0]&cell[0][0]。然后通过lowbit和打表法的方式就能快速求出所能填入的数字

int lowbit(int n)
{
   return n&-n;
}

//返回最低位的1,如n=12(0000 1100),函数返回4(0000 0100)

【】像这样的二进制优化的方法还可以用在有向图的一些题目中呢

【】例如,给你一个有向图,要求你计算出任意一个节点可以去到多少节点?

【】这里呢,我们可以定义一个bitset容器 f[nodeNum],f[n]中的1表示从n节点能到达1所在位置的那个节点,假设a1,a2,a3.....am是能从n节点一步到达的所有节点(即n节点与a节点直接相连且从n指向a),那么让  f[n]=f[a1] | f[a2] | ....f[am](或运算求并集),所以f[n].count()就是能从n节点到达其它节点的数目啦。  注意:这里要先算出子节点的数据哟,所以顺序小伙伴自己想想吧!!!

【】对啦,在背包问题中也有使用到二进制优化,只不过用法和这里完全不同,感兴趣的可去看看!

【】求赞!!!(*^▽^*)(*^▽^*)

猜你喜欢

转载自blog.csdn.net/qq_65120254/article/details/125571502