在做算法题时,我们常常需要用到一个能够表示“无穷大”的值INF,最容易想到的,我们可以把INF设为0x7fffffff,因为这是32位int的最大值。如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择。但是更多情况下,0x7fffffff并不是一个最好的选择,比如在Dijkstra算法中,我们使用松弛操作:

if (dist[u] + weight[u][v] < dist[v])
dist[v] = dist[u] + weight[u][v];

如果uv之间没有边,那么weight[u]=INF,如果此时将INF取作0x7fffffff,那么dist[u] + weight[u][v]就会向上溢出而变成负数,我们的松弛操作便出错了!

准确来说,0x7fffffff在作为32位整数的情况下不能满足无穷大加无穷大依然是无穷大这个条件,一旦溢出就变成了一个很小的负数。

可以考虑这样一个取值INF=0x3f3f3f3f0x3f3f3f3f的十进制是1061109567,是109级别的(和0x7fffffff一个数量级),而一般场合下的数据都是小于109的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。

另一方面,由于一般的数据都不会大于109,所以当我们把无穷大加上一个数据时,它并不会溢出。事实上0x3f3f3f3f + 0x3f3f3f3f = 0x7E7E7E7E,非常大但却没有超过32位int的表示范围,所以满足了我们“无穷大加无穷大依然是无穷大”的需求。

最后,之所以选择0x3f3f3f3f而不是0x3f000000,是因为如果我们想要将某个数组快速初始化为某个值,通常会使用cstring头文件中的函数memset(a, 0, sizeof(a)),方便又高效。因为memset按字节操作的(所以通常只能用来初始化数组为全0或全-1),所以我们只需要memset(a, 0x3f, sizeof(a)),就可以把数组全部初始化为0x3f3f3f3f