优化碰撞检测C ++

时间:2017-04-25 20:47:59

标签: c++ optimization

这是一个以

的形式输入的程序

2MU133 -34.94 -69.13 0.468 -0.900 第一个是汽车的ID,第二个是x-Pos,第三个是y-Pos,第一个是x-Velocity,第五个是y-Velocity。一旦两辆车之间的距离达到10,它们就会碰撞并蒸发。 我的程序运行正常,但我想知道是否有任何修改我应该这样做,它可以在大规模的数据上运行得更快,因为现在它有点慢。

#include <iostream>
#include <tuple>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
using std::cin;
using std::cout;
using std::string;
using std::make_tuple;
using std::tuple;
using std::vector;
using std::get;
using std::sqrt;
using std::sort;
bool tupleCompare(tuple<string, string, double> first,
                  tuple<string, string, double> second)
{
    return get<2>(first) < get<2>(second);
}

tuple<string, string, double> willCollide(tuple<string, double, double, double, double> car1,
                                          tuple<string, double, double, double, double> car2)
{
    double posDifX = get<1>(car1) - get<1>(car2);
    double posDifY = get<2>(car1) - get<2>(car2);
    double velDifX = get<3>(car1) - get<3>(car2);
    double velDifY = get<4>(car1) - get<4>(car2);

    double a = velDifX * velDifX + velDifY * velDifY;
    double b = 2 * (posDifX * velDifX + posDifY * velDifY);
    double c = posDifX * posDifX + posDifY * posDifY - 100;
    double possibleSol = b * b - 4 * a * c; // b^2-4ac
    double sol1, sol2;
    if ((a == 0) || possibleSol < 0)
    { //check for a = 0 or b^2-4ac < 0
        return make_tuple("0", "0", 0);
    }
    else
    {
        sol1 = (-b + sqrt(possibleSol)) / (2 * a);
        sol2 = (-b - sqrt(possibleSol)) / (2 * a);
        if (sol1 <= sol2 && sol1 > 0)
        {
            return make_tuple(get<0>(car1), get<0>(car2), sol1);
        }
        else if (sol2 <= sol1 && sol2 > 0)
        {
            return make_tuple(get<0>(car1), get<0>(car2), sol2);
        }
        else
        {
            return make_tuple("0", "0", 0);
        }
    }

}

bool containString(vector<string> colliedCars, string check)
{
    for (int i = 0; i < colliedCars.size(); i++)
    {
        if (check == colliedCars[i])
        {
            return true;
        }
    }
    return false;
}

int main()
{
    vector<tuple<string, double, double, double, double> > collectionOfCars; //All info of cars
    vector<tuple<string, string, double> > collision; //all possible collision
    vector<string> hasCollided; //store ID of cars already collid
    vector<tuple<string, string, double> > collisionResult; //result of collision
    string ID;
    double xPos, yPos, xVel, yVel;
    while (cin >> ID >> xPos >> yPos >> xVel >> yVel)
    { //read in info about cars
        collectionOfCars.push_back(make_tuple(ID, xPos, yPos, xVel, yVel));
    }
    for (int i = 0; i < collectionOfCars.size(); i++)
    { //test for time of collision for different pairs of cars
        for (int j = i + 1; j < collectionOfCars.size(); j++)
        {
            tuple<string, string, double> result =
                    willCollide(collectionOfCars[i], collectionOfCars[j]);
            if (get<0>(result) != "0")
            {
                collision.push_back(result);
            }
        }
    }
    sort(collision.begin(), collision.end(), tupleCompare);
    for (int k = 0; k < collision.size(); k++)
    {
        if (!containString(hasCollided, get<0>(collision[k]))
                && !containString(hasCollided, get<1>(collision[k])))
        {
            hasCollided.push_back(get<0>(collision[k]));
            hasCollided.push_back(get<1>(collision[k]));
            collisionResult.push_back(collision[k]);
        }
    }
    cout << "there are " << collectionOfCars.size() << " vehicles" << "\n";
    cout << "collision report" << "\n";
    if (collisionResult.size() == 0)
    {
        cout << "none" << "\n";
    }
    else
    {
        for (int i = 0; i < collisionResult.size(); i++)
        {
            cout << "at " << get<2>(collisionResult[i]) << " "
                    << get<0>(collisionResult[i]) << " collided with "
                    << get<1>(collisionResult[i]) << "\n";
        }
    }
    cout << "the remaining vehicles are" << "\n";
    if (hasCollided.size() == collectionOfCars.size())
    {
        cout << "none" << "\n";
    }
    else
    {
        for (int j = 0; j < collectionOfCars.size(); j++)
        {
            if (!containString(hasCollided, get<0>(collectionOfCars[j])))
            {
                ID = get<0>(collectionOfCars[j]);
                xPos = get<1>(collectionOfCars[j]);
                yPos = get<2>(collectionOfCars[j]);
                xVel = get<3>(collectionOfCars[j]);
                yVel = get<4>(collectionOfCars[j]);
                cout << ID << " " << xPos << " " << yPos << " " << xVel << " "
                        << yVel << "\n";
            }
        }
    }
}

1 个答案:

答案 0 :(得分:-1)

您正在使用O(n^2)算法,其中n是汽车数量。也就是说,对于每辆车,您检查其他所有车并检查是否有碰撞。您可以使用quad tree将其变为O(n * log(n)),从而做得更好。这应该可以显着提高大n的性能。

请注意,有许多其他空间索引数据结构,但四叉树在所有此类数据结构中相对容易实现。

相关问题