【问题标题】:How to visit a pair of elements in an array only once?如何只访问数组中的一对元素一次?
【发布时间】:2012-04-23 14:14:18
【问题描述】:

我正在为一个小型 2D 游戏编写物理程序,我需要检查屏幕上的每个对象与屏幕上的所有其他对象。那是O(N^2),我不太喜欢。

我的想法:

for (var i = 0; i < objects.length; i ++)
    for (var j = 0; j < objects.length; j ++)
        if (collide(objects[i], objects[j])) doStuff(objects[i], objects[j]);

这是不必要的,我将多次检查相同的对象。我怎样才能避免这种情况?我想有一个矩阵,这将是n*n(假设n是对象的数量),然后每次我访问一对对象时我都会这样做:

visited[i][j] = 1;
visited[j][i] = 1;

然后,我将始终知道我访问了哪对对象。

这可行,但是,我需要再次设置所有这些单元格,n*n 次,只是在开始时将它们全部设置为 0!也许,我可以将所有内容设置为[],但这对我来说似乎仍然不是一个可行的解决方案。有更好的吗?

显然,我选择的语言是 Javascript,但我对 C、C++ 和 Python 的了解比较流利,所以你可以用它们回答(虽然 Javascript、C 和 C++ 的语法几乎相同)。

【问题讨论】:

  • 如果性能是一个问题,您可能想开始使用四叉树。
  • 我觉得没必要……屏幕上通常有
  • 在那种情况下,是的,这不值得麻烦。

标签: javascript arrays performance algorithm matrix


【解决方案1】:

如果您的精灵有最大尺寸,您可以对数组进行排序并跳过比较屏幕上 vert+maxsize 较低的东西...

【讨论】:

    【解决方案2】:

    你不会避免 O(n^2),但你可以减少一半:

    for (var i = 0; i < objects.length; i ++)
        for (var j = i; j < objects.length; j ++)
            if (collide(objects[i], objects[j])) doStuff(objects[i], objects[j]);
    

    假设碰撞是对称的。如果它也是自反的,并且碰撞测试很昂贵,您可以将doStuff(object[i], object[i]) 移出内部循环以避免测试碰撞并从i+1 开始内部循环

    【讨论】:

    • 啊哈!该死的,我怎么没想到……无论如何,谢谢。
    • @souldcheck,另外,我将把什么切成两半? n,还是 n*n?有很大的不同!
    • @Bane 你将有 n*(n+1)/2 个测试而不是 nn,所以大约是 n 的一半n
    • 我猜这很酷。我会选择j = i + 1 以避免检查对象。
    猜你喜欢
    • 2018-09-13
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-06-26
    • 2021-09-19
    相关资源
    最近更新 更多