图论中的memset0x3f

写此博客的背景

相信有很多同学在看别人图论专题的题解、板子的时候经常看到下面两句:

const int INF = 0x3f3f3f3f;
memset(d, INF, sizeof(d));

或者下面这样:

memset(d, 0x3f, sizeof(d));

很多同学都不明所以,只知道是将d数组中的所有元素初始化成INF,但是至于为什么选用0x3f3f3f3f和函数memset的原理都不清楚,看到别人这样用,自己也这样用,不清楚为什么,于是前几天同学来问我的时候,就出现了以下WA的代码片段:

const int INF = 1e5;
// ...
memset(d, INF, sizeof(d));

以及:

const int INF = 0x3f3f3f3f;
// ...
memset(a, INF, sizeof(a));
memset(b, INF, sizeof(b));
// ...
ans = min(ans, a[i][k] + a[k][j] + b[i][j]);

如果清楚了上面两个问题,这些bug就可以避免。故写此篇博客,讲解下0x3f3f3f3fmemset的原理和使用注意事项。

memset的原理

C++API文档中的解释与函数原型

可以看到该函数本身是用来初始化字符串(该函数位于string.h中,为C语言头文件,故这里的字符串即char数组,而不是C++中的string),但是参数列表中的第一个参数为void*,再加上C语言的一些特性,该函数也可以对其他类型的数组进行初始化,但是会存在一些其他的问题,下面进行说明。

我们知道在C语言中,char类型占1个字节,而int类型占4个字节。memset在对字符串进行初始化时为逐字符初始化,即每个字节都被初始化。同样的,在使用memset对整型数组进行初始化时,会把每个元素的每个字节初始化成ch

可能干说理论有点迷糊,所以下面结合一段代码解释。

#include <cstdio>
#include <cstring>
int main() {int a[5];memset(a, 1, sizeof(a));for (int i = 0; i < 5; i++) {printf("%d\n", a[i]);}return 0;
}

运行结果:

16843009
16843009
16843009
16843009
16843009

你会发现初始化的结果并不是1。
事实上,16843009写成二进制如下

对应我刚刚在前面说的,一个int类型为4字节,这里如果把这个数的4字节拆开看的话,每一位都是1。也就是说,它会把每一字节都填充上1。

memset(d, 1e5, sizeof(d));

这段代码的问题也就比较明显了,不过需要注意的是,由于为逐字节初始化,所以超过一个字节的内容会被自动截断,也就是说,1e5只会保留它的低8位,也就是10100000。

由于int类型储存位补码,最高位是符号位,当使用1e5对代码进行初始化的时候符号位被置为1,变成了负数。同理,这也就是为什么上面的代码在使用memset时,使用0x3f和0x3f3f3f3f等价的原因,但是。

使用memset初始化一定要慎重,对于整形数组,一般只用来初始化0、-1、0x3f这几个数字,其他的建议使用循环初始化,初始化其他值时尽量用for来初始化,或者使用fill函数和fill_n函数。

0x3f3f3f3f的原理

0x是16进制的标志,0x3f3f3f3f表示的十进制和二进制见下图。

作为无穷大,一个数除了要保证足够大外,还要保证不能溢出。
使用上面这个值的主要原因是,两个0x3f3f3f3f的和只比int类型的最大值小一点,这样在两个无穷相加时能够保证不会溢出。

同理,对于long long类型,可以使用0x3f3f3f3f3f3f3f3f来进行初始化
这个原理知道了之后就能解释为什么刚刚上面的第二段WA掉的代码问题在哪了:
取0x3f3f3f3f作为INF的话,只能保证两个INF相加不会溢出,但是三个INF就会溢出了,在下面这段代码的min中实际上三个数的和可能为负,导致结果错误。

ans = min(ans, a[i][k] + a[k][j] + b[i][j]);

这里可以加一个判断条件,或者适当降低INF的值,来避免这个问题。

总结

  1. 使用memset初始化一定要慎重,一般只用来初始化0、-1、0x3f这几个数字,其他的建议使用循环初始化,其他值尽量用for循环吧。
  2. 作为无穷大,一个数除了要保证足够大外,还要保证不能溢出。
    使用0x3f3f3f3f作为INF主要原因是,两个0x3f3f3f3f的和只比int类型的最大值小一点,这样既能保证一般情况下的足够大,在两个无穷相加时还能够保证不会溢出。

图论中的0x3f和memset使用注意事项(较详细)相关推荐

  1. 图论中的基础概念总结

    总结下图论中的各种基础概念 所以有部分定义直接搬运了度娘啦~ 子图 设   为两个图(同为无向图或同为有向图),若   且   ,则称G'是G的子图,G是G'的母图,记作   ,又若   且   ,则 ...

  2. 拉普拉斯算子属于卷积方法吗_二维图像中的Laplace算子和图论中的Laplacian矩阵...

    最近在阅读 如何理解 Graph Convolutional Network(GCN)?​www.zhihu.com 接触到了图论中的Laplacian矩阵,定义为 , 是Laplacian矩阵, 是 ...

  3. 鲍尔.爱迪斯生前在图论中未完成的问题

    鲍尔.爱迪斯生前在图论中未完成的问题 F.R.K.淳(F.R.K.Chung) 盘西维尼亚大学数学系 (Department of Mathematics, University of Pennsyl ...

  4. 如何计算图论中的模块化modularity指标,图论中的社区检测算法——Louvain community

    图论中的社区检测算法--Louvain community 前言 模块化指标介绍 数学定义 Matlab代码实现 使用实例 community_louvain函数 参考文献 前言 在过去的十年中,人们 ...

  5. 图论中握手定理的详细解释

    图论中握手定理的详细解释

  6. 多智能体中的图论——图论中的定义(一)

    目前人工智能分为:大数据智能,跨媒体智能,群体智能,混合增强智能,自主无人系统五类,若想要深入群体智能则图论的基础是非常必要的! 目录 一.引言 1.1.专业词汇: 1.2.图基交互模型 1.2.1. ...

  7. 图论中的聚类系数(Clustering coefficient)简单介绍

    目录 前言 介绍 局部聚类系数 全局聚类系数 前言 在GraphSage论文的理论分析部分,涉及到一个概念叫做"Clustering coefficient",直译过来就是聚类系数 ...

  8. C语言中的scanf对应java中的,什么是C++中的scanf,memset和一对夫妇在Java中的含义?...

    所以我一直在努力理解一个算法,并且我在互联网上找到了一个C++代码,但问题是我知道Java,但对C++真的不熟悉,所以我在理解时遇到了一些麻烦.这部分特别:什么是C++中的scanf,memset和一 ...

  9. 图论中的顶点覆盖理解

    图论中的顶点覆盖 1)基础知识 图G(V,E),表示有一组顶点V,和一组边缘E⊆V*V,连接同一对顶点的两条或两条以上的边成为平行边:孤立顶点是不与其他顶点相邻的顶点.循环是具有相同顶点的边:图的边可 ...

  10. jQuery 在Table中选择input之类的东西注意事项

    jQuery 在Table中选择input之类的东西注意事项: 如果不在td标签中,是不能进行正确选择的: <table id="tblFormId"><tr&g ...

最新文章

  1. android ios 7 双环,安卓机泪奔 库克嘲笑Android 7安装率不及iOS 10零头
  2. ECMAScript 6教程 (一)
  3. php中常用的全局变量有,在PHP中如何使用全局变量的方法详解
  4. raspberry pi_在Raspberry Pi上试用Docker
  5. 【Antlr】cannot create implicit token for string literal in non-combined grammar xx
  6. 反欺诈的这几个重点内容值得您关注
  7. 立根铸魂,麒麟信安携手欧拉共推操作系统产业新发展
  8. 河北等保测评机构项目测评收费价格标准参考
  9. python3表白代码弹窗_抖音整蛊表白电脑弹窗代码大全
  10. css绘制星星闪烁,CSS3 闪烁的星星
  11. C语言实现打印平行四边形
  12. 本科论文的标准格式是什么样的?
  13. 《区块链技术进阶与实践》之积分系统示例讲解
  14. Java内存中神奇的64MB
  15. Peewee的基本使用
  16. Flutter 仿网易云音乐App
  17. Docker在自动化测试中的实践应用,看了必有提升
  18. 【docker基础操作命令】(一)启动命令和镜像命令
  19. 代码改变生活-文件重命名
  20. 影视剪辑,PR剪辑蒙太奇手法的认识

热门文章

  1. 【论文笔记-01】Re-ranking Person Re-identification with k-reciprocal Encoding
  2. 记一次kubernetes的搭建遇坑coredns状态为CrashLoopBackOff并不断重启
  3. 如何查看浏览器的DNS 缓存信息
  4. linux源文件安装,Linux下的源文件安装
  5. ubuntu 20.04 设置静态ip
  6. 异步方法中取消异步操作
  7. win无线网卡怎么进入监听模式_win10系统卸载网卡驱动的操作方法
  8. w10需要计算机管理员才能删除,如何解决删除文件需要管理员权限win10_win10你需要提供管理员权限才能删除的解决方法...
  9. js生成[n,m]的随机数公式,存入一个数组中,并排序
  10. [收藏] Flash闪存颗粒和工艺知识深度解析