【发布时间】:2020-11-20 17:45:39
【问题描述】:
我正在处理旅行推销员问题,并且正在查看以下版本:
城镇是二维空间中的点,从每个城镇到所有其他城镇都有路径,长度是点之间的距离。因此,实现简单的解决方案非常容易,您可以检查n 点的所有排列并计算路径的长度。
然而,我发现对于n >= 10 ,编译器做了一些魔术并打印出一个肯定不是实际最短路径的值。我用Microsoft visual studio compiler in release mode with the default settings 编译。对于值(10,30),它会思考 30 秒,然后返回一些看起来可能正确但不是正确的数字(我以不同的方式检查)。对于 n > 40,它会立即计算出一个结果,并且始终是2.14748e+09。
我正在寻找编译器在不同情况下的作用的解释((10,30) 案例真的很有趣)。还有一个例子,这些优化比只是旋转到世界尽头的程序更有用。
vector<pair<int,int>> points;
void min_len()
{
// n is a global variable with the number of points(towns)
double min = INT_MAX;
// there are n! permutations of n elements
for (auto j = 0; j < factorial(n); ++j)
{
double sum = 0;
for (auto i = 0; i < n - 1; ++i)
{
sum += distance_points(points[i], points[i + 1]);
}
if (sum < min)
{
min = sum;
s_path = points;
}
next_permutation(points.begin(), points.end());
}
for (auto i = 0; i < n; ++i)
{
cout << s_path[i].first << " " << s_path[i].second << endl;
}
cout << min << endl;
}
unsigned int factorial(unsigned int n)
{
int res = 1, i;
for (i = 2; i <= n; i++)
res *= i;
return res;
}
【问题讨论】:
-
你对
factorial(n)的实现是什么?它可能溢出了。 -
你为什么还要使用阶乘?你应该只看
next_permutation的返回值。 -
而不是责备优化(如果定义了行为,则不允许返回不正确的结果),您应该尝试一些调试。对于初学者,在每次迭代结束时跟踪
min的值。确保next_permutation做了你认为应该做的事情——可能会做,但这属于调试时需要验证的标准内容。 (对于加分:注意2.14748e+09可能是INT_MAX的值。) -
编译器会变魔术。 That is their job.
-
@JaMiT 我知道这取决于,但我应该期望 w8 30 多长时间!排列组合?