首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >位图问题性能提升

位图问题性能提升
EN

Code Review用户
提问于 2014-08-21 23:18:15
回答 1查看 572关注 0票数 9

问题陈述输入是一个矩形位图,如: 0001 0011 0110,任务是为每个黑色(0)“像素”找到距离最近的白色(1)“像素”。因此,上面的输出应该是:3 2 1 0 2 1 0 0 1 0 0 0 1

下面是一个工作的,评论很多的78行解决方案.不过,这太天真了。我怎样才能让它更快?我知道我可以在以给定的零为中心的矩形中搜索,但我不确定我是否需要它那么复杂。我只想在4s下运行它,在奔腾III上输入200*200。

代码语言:javascript
复制
#include <stdio.h>
#include <vector>
#include <utility>

using namespace std;

typedef unsigned short T;

//Maximum size of the array
const size_t MAX = 200;

//Converts string to unsigned integer
T atou(char* s) {
    T x = 0;
    while(*s) x = x*10 + *(s++) - '0';
    return x;
}

//Calculates absolute value
T abs(int a) {
    if(a >= 0) return a;
    else return -a;
}

int main() {
    T testCases, n, m, i, j, min, curDist;
    T A[MAX][MAX];
    char row[MAX];
    //Storing coordinates (i,j) of ones and zeroes from the input matrix
    //hopefully saves a bit of time searching for closest ones
    vector< pair<T,T> > cOnes;
    vector< pair<T,T> > cZeroes;
    pair<T,T> nextPair;
    scanf("%hu",&testCases);
    while(testCases--) {
        //Input matrix is n X m
        scanf("%hu",&n);
        scanf("%hu",&m);
        //Starting from i=1, j=1 for clarity: dealing with i-th row, j-th column
        for(i = 1; i <= n; i++) {
            scanf("%s",row);
            for(j = 1; j <= m; j++) {
                //But then have to subtract one when dealing with char[]
                A[i][j] = atou(&row[j-1]);
                if(row[j-1] == '1') {
                    cOnes.push_back(pair<T,T>(i,j));
                    //Clearing the array for the next test case
                    A[i][j] = 0;
                }
                else cZeroes.push_back(pair<T,T>(i,j));
            }
        }
        //For all zeroes find the closest one
        while(!cZeroes.empty()) {
            nextPair = cZeroes.back();
            i = nextPair.first;
            j = nextPair.second;
            cZeroes.pop_back();
            std::vector< pair<T,T> >::iterator it = cOnes.begin();
            min = abs(it->first - i) + abs(it->second - j);
            while(it != cOnes.end()) {
                curDist = abs(it->first - i) + abs(it->second - j);
                if(curDist < min) min = curDist;
                it++;
            }
            A[i][j] = min;
        }
        //Print the result
        for(i = 1; i <= n; i++) {
            for(j = 1; j <= m; j++) {
                printf("%hu ", A[i][j]);
                A[i][j] = 0;
            }
            printf("\n");
        }
    }
    return 0;
}
EN

回答 1

Code Review用户

发布于 2014-08-22 00:23:25

首先,将输入中的所有1's转换为输出中不能显示的值(例如-1),并保存每个位置。

然后,从每个-1开始,我基本上会做一个修改过的洪水填充。查看它的每个邻居,其中任何一个当前为0,设置为1并保存该位置。对输入中的每个其他-1重复。

然后遍历所有保存的地点。这些值为零的每个邻居,设置为2(并且,再次保存这些位置)。

重复,直到到达一个没有在输入中找到任何0s的迭代(显然,增加这些外部迭代的距离数)。

最后,把所有的-1s都换成了0s。

就您的代码本身而言,它被标记为C++,但是很多代码都非常类似于C。您有几个vectors,但是大多数C++程序员宁愿避免的一些C-东西(例如,printfscanf和内置数组)。对于您使用过的一些名称(例如,cZeroescurrDist),我也不太兴奋。我更希望看到更完整的名字(例如,current_distance,或者,如果您坚持camelCase,currentDistance)。

票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/60760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档