用于计算网格中点数的更好算法

时间:2015-08-17 05:46:37

标签: c++ algorithm

假设我在[0,1] * [0,1]中有一个点P,并且[0,1]被分成m(比如200)个网格。我使用A[m][m]来表示[以P为中心,长度为2h的小方块]是否覆盖每个网格。因此,对于点P,A[i][j]要么是(增加)1还是0。

假设我有n个这样的点(P1,...,Pn),我想计算A(对于每个点Pi,我重做上面的过程,加1或者不加1)。我怎样才能有效地(使用C ++)而不是编写3层for循环来检查每个网格和每个点(So O(nm ^ 2))?

我用C ++尝试了naive 3 for循环。使用一些向量化操作(比如vector<= number用于比较n个数字,A[bool vector, bool vector]进行子集化)需要更长的时间。

由于C ++通常比R快,是否有任何智能方法来实现此过程?

#include <Rcpp.h>
#include <cmath>
using namespace Rcpp;

// [[Rcpp::export]]

double myfun(NumericVector u, NumericVector v)
{
    double n = u.size();
    double A[200][200] = {0};
    double pos[200];
    int i = 0, j = 0, k = 0;

    for (i = 0; i < 200; i++)
    {
        pos[i] = (double)i / 201;
    }

    for (k = 0; k < n; k++)
    {
        for (i = 0; i < 200; i++)
        {
            for (j = 0; j < 200; j++)
            {
                if ( (fabs(u[k] - pos[i]) <= h) && (fabs(v[k] - pos[j]) <=h ) )
                {
                    A[i][j]++;
                }
            }
        }
    }

    double s = 0, avg = 0;

    for (i = 0; i <200; i++)
    {
        for (j = 0; j < 200; j++)
        {
            s += A[i][j];
        }
    }
    avg = s / (200 * 200);
    return (avg);
}

1 个答案:

答案 0 :(得分:1)

两个内部循环仅确定网格中点的索引。但您可以直接计算索引:

int i = (int)(u[k]*200);
int j = (int)(v[k]*200);

您可能还需要检查ij是否未达到索引200.但这只会在u[k] == 1.0v[k] == 1.0时发生。

double n = u.size();
double A[200][200] = {0};

for (int k = 0; k < n; k++)
{
    int i = (int)(u[k]*200);
    int j = (int)(v[k]*200);
    if (i == 200)
        i = 199;
    if (j == 200)
        j = 199;

    A[i][j]++;
}