为什么INTMAX_MAX在这里给出了错误的结果?

时间:2016-01-07 06:48:44

标签: c++ numeric-limits

我遇到了一个问题,要求我找到任意一对顶点之间最便宜的路径。我为解决方案实现了Floyd Warshall算法。但是我的程序中有一个奇怪的错误。我使用intmax_t来避免溢出,但是如果我使用INTMAX_MAX而不是INT_MAX来获得无限代价来表示两个顶点没有直接连接,那么我得到了错误的答案。为什么会这样?

#include <bits/stdc++.h>
using namespace std;
struct _ { ios_base::Init _i; _() { cin.sync_with_stdio(0); cin.tie(0); } } _;

#define endl '\n'
#define int intmax_t
#define in(x) for (auto& i: x)
#define test int _t; cin >> _t; for (int i=1; i<=_t; i++) {

signed main()
{
    int v, e, ans=INT_MIN;
    cin >> v >> e;
    int g[v+1][v+1];
    for (int i=1; i<=v; i++)
        for (int j=1; j<=v; j++)
            g[i][j]=INT_MAX;
    for (int i=0; i<e; i++)
    {
        int x, y, p;
        cin >> x >> y >> p;
        g[x][y]=g[y][x]=p;
    }
    for (int i=1; i<=v; i++)
        for (int j=1; j<=v; j++)
            for (int k=1; k<=v; k++)
                g[j][k]=min(g[j][k], g[j][i]+g[i][k]);
    for (int i=1; i<=v; i++)
        for (int j=1; j<=v; j++)
            if (g[i][j]!=INT_MAX && i!=j)
                ans=max(ans, g[i][j]);
    cout << ans;
}

如果我用INTMAX_MIN替换INT_MIN,用INTMAX_MAX替换INT_MAX,我得到的结果不正确。

示例案例:

使用INT_MAX:http://ideone.com/ffmv7P

使用INTMAX_MAX:http://ideone.com/vjMCuE

附录:该程序专门用于解决竞争性编程问题。请保持正确的编码习惯&#34;给自己的建议。如果您愿意回答,您会发现预处理程序指令在这种情况下对可读性几乎没有影响。他们是有原因的,我不是傻瓜。如果您没有竞争性编程经验,请不要责怪我。谢谢。

2 个答案:

答案 0 :(得分:1)

您正在添加号码并有可能发生溢出。使用jan时,您需要使用可能低于INT_MAX范围的数字初始化单元格(这是单元格的真实类型)。 intmax_t可能会INT_MAX+INT_MAX而不会溢出而intmax_t肯定不会溢出。

你遇到整数溢出,理论上它具有未定义的行为。实际上很可能它在比较中不能很好地进行比较,因为整数溢出会包裹到负数,使INTMAX_MAX+INTMAX_MAX远小于INTMAX_MAX+INTMAX_MAX(它甚至可能变为负数)。

如果你的编译器INTMAX_MAX具有相同的范围int(这不是那么不切实际),那么在这两种情况下你的代码都会失败。

答案 1 :(得分:1)

显然,您不能将INTMAX_MAX存储在int类型的变量中。你得到一个溢出,导致未定义的行为。实际上,您通常会获得INTMAX_MAX的最后32位,这些位模式与(int)-1相同。

另一方面,将int与INTMAX_MAX进行比较意味着int将转换为intmax_t,但只要类型不同(它们实际上是这样),int就永远不会等于INTMAX_MAX。