在矩阵中查找元素,最小成本从一个点开始

时间:2012-11-05 06:41:56

标签: c++ algorithm search

我有n * n矩阵,我想从矩阵中找到具有最小成本的元素,节点的成本意味着成本= Manhattandistance(startingnode,node)+ costof(node)其中起始节点是节点从哪个角度来看我的搜索!

我只用了4个循环来做它并且它可以工作但是我想要优化它并且我做了类似bfs的东西:我使用了队列并首先添加了起始节点,之后在while循环中我弹出了节点从队列中并使用Manhatttan 1将该节点周围的所有元素添加到队列中。我这样做的同时我刚从队列中弹出的节点的距离+整个矩阵的最小价格(我从一开始就知道) )小于我刚刚找到的最低价格(我将刚刚弹出的节点的价格与min进行比较)如果它更大我会停止搜索,因为我找到的最小节点是最低可能值。问题是这个算法可能会慢,因为我使用std :: queue?它比4 for for循环版本的工作时间更长。 (我还使用了一个标志矩阵来查看我添加到队列时检查的元素是否已经添加)。最耗时的代码块是我扩展节点的部分不知道为什么我只检查元素是否有效我的意思是它的坐标小于n且大于0如果确定我将元素添加到队列中!

我想知道如何改进这一点,或者它是否是另一种方法!希望我足够明确。

这是代码的一部分,需要很长时间:

if((p1.dist + 1 + Pmin) < pretmincomp || (p1.dist + 1 + Pmin) < pretres){
                std::vector<PAIR> vec;  
                PAIR pa;
                int p1a=p1.a,p1b = p1.b,p1d = p1.dist;
                if(isok(p1a+1,p1b,n)){
                    pa.a = p1a + 1;
                    pa.b = p1b;
                    pa.dist = p1d + 1;

                    vec.push_back(pa);
                }
                if(isok(p1a-1,p1b,n)){
                    pa.a = p1a - 1;
                    pa.b = p1b;
                    pa.dist = p1d + 1;
                    vec.push_back(pa);
                }

                if(isok(p1a,p1b+1,n)){
                    pa.a = p1a;
                    pa.b = p1b + 1;
                    pa.dist = p1d + 1;
                    vec.push_back(pa);
                }
                if(isok(p1a,p1b -1 ,n)){
                    pa.a = p1.a;
                    pa.b = p1.b - 1;
                    pa.dist = p1d + 1;
                    vec.push_back(pa);
                }



                for(std::vector<PAIR>::iterator it = vec.begin();
                         it!=vec.end(); it++){
                    if(flags[(*it).a][(*it).b] !=1){
                        devazut.push(*it);
                        flags[(*it).a][(*it).b] = 1;
                    }
                }

1 个答案:

答案 0 :(得分:1)

您正在处理shortest path problem,可以使用BFS(如果图表未加权)或A* algorithm有效解决 - 如果您在图表上有一些“知识”,可以估算从每个节点找到目标所花费的成本。

您的解决方案与BFS非常相似,只有一个区别 - BFS还维护了visited - 您已访问过的所有节点。这个visited集的想法是你不需要重新访问已经访问过的节点,因为通过它的任何路径都不会短于你在第一次访问这个节点时找到的最短路径。
请注意,如果没有设置visited - 每个节点都会重新访问很多次,这会使算法效率很低。

BFS的伪代码(带访问集):

BFS(start):
  q <- new queue
  q.push(pair(start,0)) //0 indicates the distance from the start
  visited <- new set
  visited.add(start)
  while (not q.isEmpty()):
     curr <- q.pop()
     if (curr.first is target):
        return curr.second //the distance is indicated in the second element
     for each neighbor of curr.first:
        if (not set.contains(neighbor)): //add the element only if it is not in the set
           q.push(pair(neighbor,curr.second+1)) //add the new element to queue
           //and also add it to the visited set, so it won't be re-added to the queue.
           visited.add(neighbot) 
  //when here - no solution was found
  return infinity //exhausted all vertices and there is no path to a target