2d数组元素之间的距离

时间:2011-04-02 11:02:01

标签: c++ algorithm multidimensional-array

我正试图解决这个问题:

  

给出了一个矩形位图   大小n * m。位图的每个像素都是   白色或黑色,但至少   一个是白色的。第i行的像素   第j列称为像素   (I,J)。两个像素之间的距离   定义p1 =(i1,j1)和p2 =(i2,j2)   为:

d(p1,p2)=|i1-i2|+|j1-j2|.

任务

编写一个程序:

  

读取位图的描述   从标准输入,每个   像素,计算距离   最近的白色像素,写道   结果是标准输出。

输入

  

测试用例t的数量   第一行输入,然后是t测试用例   用空行分隔。在   每个测试用例的第一行   是一对整数n,m   由单个空格分隔,1 <= n   &lt; = 182,1 <&lt; = m&lt; = 182。在每一个   以下n行测试用例   正好一个长度为零的零字,   一行的描述   位图,是写的。在第j个   行中的位置(i + 1),1&lt; = i&lt; =   n,1&lt; = j&lt; = m,如果且仅当是,则为'1'   像素(i,j)是白色。

Output
  

在每个测试用例的第i行中,   1&lt; = i&lt; = n,应该写m   整数f(i,1),...,f(i,m)分开   单个空格,其中f(i,j)是   从像素(i,j)到的距离   最近的白色像素。

我提出的算法是:

  • 读取2d数组,如果元素为'1'(白色),则保存它的坐标。
  • 循环通过2d数组,如果元素为'0'黑色,则循环遍历所有白色坐标并找到最短距离并输出。

这是我的实施:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

struct white{
    int i;
    int j;
};

int main()
{
    int N;
    cin >> N;

    for (int z = 0; z < N; z++){
        char bitmap[182][182];

        int n,m;
        cin >> n >> m;
        vector<white> whites;

        for (int i = 1; i <= n; i++){
            string s;
            cin >> s;

            for (int j = 0; j < m; j++){
                bitmap[i][j+1] = s[j];
                if (s[j] == '1'){
                    white x;
                    x.i = i;
                    x.j = j+1;
                    whites.push_back(x);
                }
            }
        }

        int size = whites.size();

        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= m; j++){
                if (bitmap[i][j] == '0'){

                    int distance = 31223123;

                    for (int x = 0; x < size; x++){
                        int d = abs(i-whites[x].i) + abs(j-whites[x].j);
                        if (d < distance)
                            distance = d;
                    }

                    cout << distance << ' ';

                } else {
                    cout << '0' << ' ';
                }
            }
            cout << endl;
        }
    }
    return 0;
}

尽管这样做有点太慢了。请帮我提高性能,或者这个算法可能不够快?

4 个答案:

答案 0 :(得分:4)

您可以从另一端接近算法,而不是尝试计算从每个黑色位置到所有白色的距离,计算从白色元素到所有其他节点的距离。这将允许您削减许多计算:

  • 使用所有MAX_VALUE距离初始化地图
  • 每个白色
    • 将地图(pos(白色))的值设置为0
    • 将递归函数应用于白色周围的位置:
      • reduce_distance(left(pos(white)),1); reduce_distance(up(pos(white)),1)...
      • 其中reduce_distance(pos,value)定义为:
        • 如果map(pos)&lt; = value:cut,则递归算法不会改善现有值。
        • map(pos)= value:设置当前最佳距离
        • recurse:reduce_distance(left(pos),value + 1),reduce_distance(up(pos),value + 1)...

这可以减少操作次数。您还可以尝试通过智能选择白点的顺序来启发式地提高性能。想象一下1D情况,如果您按唯一坐标对点进行排序,并使用以白色有序列表的中位数开头,则左侧的任何点都不需要检查超出该第一点的位置,以便您通过选择最佳分区其余空间的下一个白点,可以改善最坏的情况。

答案 1 :(得分:2)

这是图像处理的标准问题(“距离变换”)并且存在有效的算法,参考 例如http://en.wikipedia.org/wiki/Distance_transform

答案 2 :(得分:1)

关键是要考虑你已经给出的距离函数(L1 /出租车规范),以便进行最有效的搜索。

d(p1,p2)=|i1-i2|+|j1-j2|.

enter image description here

在给定像素周围,执行搜索的顺序应为

    3
   323
  32123
 3210123
3210x0123
 3210123
  32123
   323
    3

答案 3 :(得分:1)

我建议做类似David Rodriguez的解决方案:计算从白色像素开始的距离。但是,不是进行递归的深度优先搜索,而是使用队列代替广度优先。这可以保证您只需要遍历每个像素一次。

for each pixel (p):
   cost(p) := +inf

queue := empty queue
for each white pixel (w):
    cost(w) := 0
    push(queue, w)

while queue is not empty:
    p := pop(queue)
    for each neighbour pixel (pn):
        if cost(pn) == +inf:
            cost(pn) = cost(p) + 1
            push(queue, pn)