使用0x3f3f3f3f而不是0x7fffffff表示无穷大

【问题描述】
在SPFA算法中,发现若设置inf=0x7fffffff表示无穷大,则算法输出结果错误。
后来,选择设置inf=0x3f3f3f3f表示无穷大,则算法输出结果正确。

【问题分析】
原因在于选择0x7fffffff作为无穷大,不能满足“无穷大加一个有穷的数依然是无穷大”或“无穷大加无穷大依然是无穷大”的操作。分析问题,发现在使用上述两个操作的环境下,比如各类最短路径算法中常使用的松弛操作,若选择0x7fffffff作为无穷大会溢出,导致操作结果变成一个很小的负数,从而出错。所以,在更多情况下,选择0x7fffffff作为无穷大并不是一个好的选择。

分析大牛代码,发现最精巧的无穷大常量取值是inf=0x3f3f3f3f。
事实上,0x3f3f3f3f+0x3f3f3f3f=2122219134,这非常大但没有超过32-bit int的表示范围。所以0x3f3f3f3f满足了“无穷大加无穷大依然是无穷大”的需求。


【参考文献】
https://blog.csdn.net/L_apple8/article/details/52525752

 

#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXV 100 // 最大顶点数 #define INF 0x3f3f3f // 无穷大 char vertex[MAXV][20]; // 顶点名称 int matrix[MAXV][MAXV]; // 邻接矩阵 int visited[MAXV]; // 标记数组,用于深度遍历 int queue[MAXV]; // 队列,用于广度遍历 int front = 0; // 队首指针 int rear = 0; // 队尾指针 struct Edge { int start; // 起点在vertex数组中的下标 int end; // 终点在vertex数组中的下标 int weight; // 权值 }; void createGraph(int m, int n) { int i,j; // 输入顶点名称 for (i = 0; i < m; i++) { scanf("%s", vertex[i]); } // 初始化邻接矩阵 memset(matrix, INF, sizeof(matrix)); // 输入边的信息 for (i = 0; i < n; i++) { char start[20], end[20]; int weight; scanf("%s %s %d", start, end, &weight); int u = -1, v = -1; for (j = 0; j < m; j++) { if (strcmp(start, vertex[j]) == 0) { u = j; } if (strcmp(end, vertex[j]) == 0) { v = j; } if (u != -1 && v != -1) { break; } } matrix[u][v] = matrix[v][u] = weight; } } void dfs(int u) { int v; visited[u] = 1; printf("%s ", vertex[u]); for (v = 0; v < MAXV; v++) { if (matrix[u][v] != INF && visited[v] == 0) { dfs(v); } } } void bfs(int u, int m) { int v,w; printf("%s ", vertex[u]); visited[u] = 1; queue[rear++] = u; while (front != rear) { v = queue[front++]; for (w = 0; w < m; w++) { if (matrix[v][w] != INF && visited[w] == 0) { printf("%s ", vertex[w]); visited[w] = 1; queue[rear++] = w; } } } } int main() { int m, n,i; scanf("%d %d", &m, &n); createGraph(m, n); memset(visited, 0, sizeof(visited)); char start[20]; scanf("%s", start); int u = -1; for (i = 0; i < m; i++) { if (strcmp(start, vertex[i]) == 0) { u = i; break; } } dfs(u); printf("\n"); memset(visited, 0, sizeof(visited)); front = rear = 0; bfs(u, m); printf("\n"); return 0; }看看这段代码有没有问题,并给出修改后的代码
05-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值