如何提高对Dijkstra算法的修改效率?

穿过EvreYüksel的中途

问题是我的计算机科学作业的一部分。作业包括5种不同类型的学生,他们通过给定的加权无向节点图旅行,其中每个学生都有不同的方法。第五名学生是最​​困难的一个,我无法有效地实施它。

第五名学生具有秘密力量,可以在相邻节点之间传送,因此在它们之间移动需要0倍的时间。但是,要充实这个秘密力量,他需要穿越两个边缘,并且他/她在旅途的开始就没有那个秘密力量。与其他四个学生不同,他可以多次使用同一条边,因此在第一步中,他可以走N_1-> N_2和N_2-> N_1来恢复他/她的秘密力量。(S)他无法存储他/她的秘密权力,获得权力后必须立即使用。

第五名学生想知道最短的时间到达顶峰。开始时,他没有任何能量,因此他需要通过两个边沿来充电。

我尝试的方法是Dijkstra算法的修改;而不是一个节点一个节点地移动,它只考虑前两个跳跃的权重,而是从一个节点计算所有三个可能的跳跃。它考虑了所有情况,例如去节点再返回以重新充电并跳出高权重节点。它确实可以工作,而且我确实可以为给定的测试用例获得所有正确答案,但是速度很慢。我们处于2秒的限制之下,现在对于具有50000个节点和100000条边的测试用例,我的算法需要大约4秒钟的时间。

我猜问题出在邻居之间,因为有3个嵌套的for循环可以到达所有可能的3个跳跃邻居(同时也可以多次使用相同的边),这基本上使这个O(n ^ 3) (但是我不太喜欢用大号表示法,所以我不确定是否真的是这样。)

有没有人有任何想法可以提高此算法的效率,或者没有那么慢的另一种算法?

任何帮助表示赞赏!

这是代码,如果有帮助的话。

long long int HelpStudents::fifthStudent() { 
auto start = std::chrono::system_clock::now();


set< pair<long long int,int> >setds;
vector<long long int> dist(totalNodes+15,std::numeric_limits<long long int>::max());
setds.insert(make_pair(0,1));
dist[1] = 0;
bool change = false;
int counter = 0;   //these variables were just for checking some things
int max_counter = 0;
int changed_summit = 0;
int operations_after_last_change = 0;


int w1;
int w2;
int db = 0;

vector<int> neighbors;
vector<int> neighbors2;
vector<int> neighbors3;
int u;

while(!setds.empty()){
    pair<long long int,int> tmp = *(setds.begin());
    setds.erase(setds.begin());
    u = tmp.second; //vertex label
    if(dist[u] > dist[summit_no]){
        continue;
    }
    if(!change){
        counter++;
    }else{
        counter = 0;  //debugging stuff
    }
    db++;
    //cout << db2 << endl;

    operations_after_last_change++;
    max_counter = max(counter,max_counter);
    //cout << "counter: " << counter <<endl;
    change = false;
    neighbors = adjacency_map[u];  //adjacency map holds a vector which contains the adjacent nodes for the given key

    //cout << "processing: " << "(" << tmp.first << ","<< tmp.second << ") " << endl;

    for(int nb : neighbors){
        w1 = getWeight(u,nb);  //this is one jump,
        //nb is neighboor
        neighbors2 = adjacency_map[nb];
        //cout << "\t->"  << nb  << endl;
        if( nb == summit_no){
            if(dist[nb] >  dist[u] + (w1)){

                auto t = setds.find(make_pair(dist[nb],nb));
                if(t != setds.end()){
                    setds.erase(t);
                }
                dist[nb] = dist[u] + (w1);
                change = true;
                changed_summit++;
                operations_after_last_change = 0;
                //cout << "changed summit to " << (dist[u] + (w1)) << endl;

                //continue;
            }
        }

        for(int nb2: neighbors2){  //second jump
            w2 = getWeight(nb,nb2);
            //cout << "\t\t->"  << nb2  << endl;
            if( nb2 == summit_no){
                if(dist[nb2] >  dist[u] + (w1+w2)){

                    auto t = setds.find(make_pair(dist[nb2],nb2));
                    if(t != setds.end()){
                        setds.erase(t);
                    }
                    dist[nb2] = dist[u] + (w1+w2);
                    change=true;
                    changed_summit++;
                    operations_after_last_change = 0;
                    //cout << "changed summit to " << (dist[u] + (w1+w2)) << endl;

                    //continue;
                }
            }
            neighbors3 = adjacency_map[nb2];

            for(int nbf: neighbors3){  //third jump, no weight
                //cout << "\t\t\t->"  << nbf;
                if(dist[nbf] >  dist[u] + (w1+w2)){


                    auto t = setds.find(make_pair(dist[nbf],nbf));
                    if(t != setds.end()) {
                        setds.erase(t);
                    }

                    change = true;
                    dist[nbf] = dist[u] + (w1+w2);
                    if(nbf == summit_no){
                        changed_summit++;
                        operations_after_last_change = 0;
                        //cout  << endl;
                    }else{
                        setds.insert(make_pair(dist[nbf],nbf));
                        //cout << "\t\t\t\t inserted ("<<dist[nbf]<<","<<nbf<<")"  << endl;
                    }

                    //cout << "changed " << nbf << " to " << (dist[u] + (w1+w2)) << ";  path: "<< u <<" -> "<<nb<<" -> "<<nb2 << " -> " <<nbf << endl;
                    //setds.insert(make_pair(dist[nbf],nbf));
                }else{
                    //cout  << endl;
                }
            }

        }





    }
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
cout << "time passed: "<< elapsed_seconds.count() <<"   total loop: "<<db<< endl;
return dist[summit_no];
马特·蒂默曼斯

您可以制作(或更可能是想像)一个新的有图,并针对学生5可能处于的每种独特情况/状态都有一个节点-即原始图节点和计费状态(0、1或2)的组合。因为存在3个电荷状态,所以此图的节点数是原始图的3倍。

然后,您可以在此新图上使用完全普通的Dijkstra算法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何提高算法的效率?

来自分类Dev

如何使用python提高置换算法效率

来自分类Dev

在Java中使用Iterator时如何提高算法的效率?

来自分类Dev

如何使用python提高置换算法效率

来自分类Dev

如何提高循环效率

来自分类Dev

如何提高循环效率

来自分类Dev

如何提高XSLT效率

来自分类Dev

使用字典提高算法效率

来自分类Dev

提高 R 中查找算法的效率

来自分类Dev

如何提高该程序的效率?

来自分类Dev

如何提高内联函数效率?

来自分类Dev

如何提高我的特里效率?

来自分类Dev

如何提高多线程效率?

来自分类Dev

如何提高慢循环的效率

来自分类Dev

如何提高IsItAHoliday函数的效率?

来自分类Dev

如何提高AWK程序的效率

来自分类Dev

如何使用Camel提高效率?

来自分类Dev

如何提高数据生成器的效率?

来自分类Dev

如何提高DataFrame的应用功能效率?

来自分类Dev

如何使用AddChildViewController提高效率

来自分类Dev

如何提高此SQL语句的效率?

来自分类Dev

如何提高Prime Generator代码的效率

来自分类Dev

我将如何提高此脚本的效率?

来自分类Dev

如何提高我的重定向代码的效率

来自分类Dev

如何提高Lucene中的搜索查询效率?

来自分类Dev

如何提高双卷窗操作的效率?

来自分类Dev

如何提高该算法的性能?

来自分类Dev

算法的效率

来自分类Dev

Dijkstra的算法是否不修改标记顶点的距离?