【问题标题】:Merge collided bodies as one将碰撞的物体合并为一个
【发布时间】:2015-10-02 17:09:16
【问题描述】:

我正在处理一些 Javascript 中的物理内容,基本上想将碰撞的物体作为一个整体来处理。

我有一个包含所有发生碰撞的数组,一个碰撞由两个物体组成,物体 A 和物体 B。

假设发生六次碰撞,物体之间的碰撞:

  1. X 和 Y
  2. Y 和 Z
  3. C 和 D
  4. E 和 F
  5. F 和 H
  6. G 和 H

现在我想将所有以某种方式连接的物体合并为一个物体。我想要列表中的那些合并的机构。例如,在这种情况下,我想要一个如下所示的列表:

  1. X、Y 和 Z(因为 X 与 Y 碰撞,Y 与 Z 碰撞)
  2. C 和 D(因为 C 与 D 碰撞)
  3. E、F、G 和 H(因为 E 与 F、F 与 H、G 与 H 碰撞)

现在我很确定那里有一些我需要的算法,我只是不知道去哪里找,而且我没有自己解决这个问题的想法。

【问题讨论】:

  • 搜索联合查找。为这个问题制作的数据结构。

标签: algorithm collision


【解决方案1】:

在现实生活中你会如何做到这一点?

我想我会阅读每条规则。对于每条规则,我都会连接这两个部分。我最终得到的是一个blob的集合。然后我可以遍历每个图表以获取每个图表中的节点列表。每个“连接的组件”都是一个“blob”。将这个算法形式化一点可能会给出这样的结果:

// make the graph of connected components
nodes = map<symbol, pair<symbol, list<symbol>>>
for each (a, b) in rules do
    if nodes[a] is null then nodes[a] = node(a, [b])
    else nodes[a].connections.append(b)

    if nodes[b] is null then nodes[b] = node(b, [a])
    else nodes[b].connections.append(a)
loop

blobs = map<symbol, list<symbol>>
for each (a, b) in rules do

    firstNode = nodes[a]
    // do a DFS/BFS search starting from firstNode to find
    // all nodes in the connected component. whenever you
    // follow a link from a node, remove it from the node's
    // list of links. this prevents ever searching from that
    // node again since we know what component it's in already
    // add each node to the list of symbols in blobs[a]

loop

在第一个循环中,我们读取每条规则一次,然后做一定量的工作,所以规则数量是 O(n) 时间。它将为每个规则存储两个连接,就规则数量而言也是 O(n) 存储。

在第二个循环中,我们查看每个规则并对每个规则的 LHS 符号进行 DFS 或 BFS。但是,请注意,搜索只会遍历任何边一次,因此这是规则数量的 O(n) 时间。我们最终会得到一组 blob,其列表的并集将是不超过规则数量的符号集,因此也是 O(n) 存储。

所以我们有一个 O(n) 时间、O(n) 空间复杂度算法来确定 blob。渐近地说,我们能做得更好吗?显然,我们需要查看所有 n 条规则,因此时间复杂度是最优的。另请注意,该问题的任何解决方案都必须针对每个符号说明该符号最终属于哪个 blob,因此只需在输出磁带上写下答案就需要 O(n) 空间。所以这也应该是最优的。

【讨论】:

    【解决方案2】:

    如果您有一个包含所有对象的 ADT(在本例中为地图),并且您保留父 ID 以跟踪对象碰撞,您可以在恒定时间内处理每个碰撞+合并。

    // setup
    var X = {id: 1, name:'X'};
    var Y = {id: 2, name:'Y'};
    var Z = {id: 3, name:'Z'};
    var C = {id: 4, name:'C'};
    var D = {id: 5, name:'D'};
    var E = {id: 6, name:'E'};
    var F = {id: 7, name:'F'};
    var G = {id: 8, name:'G'};
    var H = {id: 9, name:'H'};
    var all = { 1:X, 2:Y, 3:Z, 4:C, 5:D, 6:E, 7:F, 8:G, 9:H };
    
    // method to merge collided objects together
    function collision(obj1, obj2) {
        var p1 = obj1.parent;
        var p2 = obj2.parent;
        if(p1 === undefined && p2 === undefined) {
            obj1.parent = obj1.id;
            obj2.parent = obj1.id;
            obj1.name += obj2.name;
            delete all[obj2.id];
        } else if(p1 !== undefined && p2 === undefined) {
            obj2.parent = obj1.parent;
            all[obj1.parent].name += obj2.name;
            delete all[obj2.id];
        } else if(p1 === undefined && p2 !== undefined) {
            obj1.parent = obj2.parent;
            all[obj2.parent].name += obj1.name;
            delete all[obj1.id];
        } else if(p1 !== undefined && p2 !== undefined && obj1.parent !== obj2.parent) {
            if(all[obj1.parent] !== undefined) {
                all[obj1.parent].name += all[obj2.parent].name;
                delete all[obj2.parent];
            } else if(all[obj2.parent] !== undefined) {
                all[obj2.parent].name += all[obj1.parent].name;
                delete all[obj1.parent];
            }
        }
    }
    
    // test
    console.log(JSON.stringify(all));
    collision(X, Y);
    collision(Y, Z);
    collision(C, D);
    collision(E, F);
    collision(F, H);
    collision(G, H);
    console.log(JSON.stringify(all));
    collision(X, E);
    console.log(JSON.stringify(all));
    

    {"1":{"id":1,"name":"X"},"2":{"id":2,"name":"Y"},"3":{" id":3,"name":"Z"},"4":{"id":4,"name":"C"},"5":{"id":5,"name":" D"},"6":{"id":6,"name":"E"},"7":{"id":7,"name":"F"},"8":{" id":8,"name":"G"},"9":{"id":9,"name":"H"}}

    {"1":{"id":1,"name":"XYZ","parent":1},"4":{"id":4,"name":"CD","父":4},"6":{"id":6,"name":"EFHG","父":6}}

    {"1":{"id":1,"name":"XYZEFHG","parent":1},"4":{"id":4,"name":"CD","父母“:4}}

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      相关资源
      最近更新 更多