Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 当查询n次时,如何改进Dijkstra算法?_Algorithm_Optimization - Fatal编程技术网

Algorithm 当查询n次时,如何改进Dijkstra算法?

Algorithm 当查询n次时,如何改进Dijkstra算法?,algorithm,optimization,Algorithm,Optimization,我目前正在解决一个问题。您可以在此处找到问题陈述: 简而言之,问题是要求查询从开始到结束的最短路径的n倍。我的解决方案是使用Dijsktra和priority\u queue并将结果缓存到hash\u map中,以防我们已经有了start。不幸的是,我的时间限制超过了很多次,我找不到更好的方法来加快它。我想知道我走对了吗?还是有更好的算法来解决这个问题 顺便说一下,由于比赛还在进行中,请不要发布任何解决方案。对我来说,一个暗示就足够了。谢谢 以下是我的尝试: #ifdef __GNUC__ #

我目前正在解决一个问题。您可以在此处找到问题陈述:

简而言之,问题是要求查询从
开始
结束
的最短路径的
n
倍。我的解决方案是使用
Dijsktra
priority\u queue
并将结果缓存到
hash\u map
中,以防我们已经有了
start
。不幸的是,我的
时间限制超过了很多次,我找不到更好的方法来加快它。我想知道我走对了吗?还是有更好的算法来解决这个问题

顺便说一下,由于比赛还在进行中,请不要发布任何解决方案。对我来说,一个暗示就足够了。谢谢

以下是我的尝试:

#ifdef __GNUC__
#include <ext/hash_map>
#else
#include <hash_map>
#endif

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <deque>
#include <queue>
#include <fstream>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#ifdef __GNUC__
namespace std {
    using namespace __gnu_cxx;
}
#endif


const int   MAX_VERTICES = 250;
const int   INFINIY = (1 << 28);
int         weight[MAX_VERTICES + 1][MAX_VERTICES + 1];
bool        visited_start[MAX_VERTICES + 1] = { 0 };

struct vertex {
    int node;
    int cost;

    vertex(int node = 0, int cost = 0)
        : node(node), cost(cost) {
    }

    bool operator <(const vertex& rhs) const {
        return cost < rhs.cost;
    }

    bool operator >(const vertex& rhs) const {
        return cost > rhs.cost;
    }
};

hash_map<int, vector<vertex> > cache;
typedef priority_queue<vertex, vector<vertex>, greater<vertex> > min_pq;

vector<vertex> dijkstra_compute_path(int start, int n) {
    min_pq pq;
    vector<vertex> path;
    vector<int> visited(n, 0);
    int min_cost = 0;
    int better_cost;
    vertex u;

    for (int i = 0; i < n; ++i) {
        path.push_back(vertex(i, INFINIY));
    }

    path[start].cost = 0;
    pq.push(vertex(start, path[start].cost));

    while (!pq.empty()) {
        // extract min cost
        u = pq.top();
        pq.pop();

        // mark it as visited
        visited[u.node] = 1;

        // for each vertex v that is adjacent to u
        for (int v = 0; v < n; ++v) {
            // if it's not visited, visit it
            if (visited[v] == 0) {
                better_cost = path[u.node].cost + weight[u.node][v]; 
                // update cost
                if (path[v].cost > better_cost) {
                    path[v].cost = better_cost;
                    pq.push(vertex(v, path[v].cost));
                }
            }
        }
    }

    return path;
}

void check_in_cache(vector<vertex>& path, int start, int no_street) {
    if (visited_start[start] == 0) {
        path = dijkstra_compute_path(start, no_street);
        cache.insert(make_pair(start, path));
        visited_start[start] = 1;
    }
    else {
        path = cache[start];
    }
}

void display_cost(int stop_at_gas_cost, int direct_cost) {
    printf("%d ", stop_at_gas_cost);
    if (stop_at_gas_cost > direct_cost) {
        printf("%d\n", stop_at_gas_cost - direct_cost);
    }
    else {
        printf("0\n");
    }
}

void handle_case_one() {
    int no_scenario;
    int dummy;
    int s, g, d;

    scanf("%d", &dummy);
    scanf("%d", &no_scenario);
    for (int i = 0; i < no_scenario; ++i) {
        scanf("%d %d %d", &s, &g, &d);
        printf("0 0\n");
    }
}

void inout_delivery_boy() {
    int no_street;
    int no_scenario;
    int restaurant;
    int gas_station;
    int destination;
    int stop_at_gas_cost;
    int direct_cost;
    vector<vertex> direct;
    vector<vertex> indirect;
    vector<vertex> d;
    int c;

    scanf("%d", &no_street);
    if (no_street == 1) {
        handle_case_one();
        return;
    }

    for (int x = 0; x < no_street; ++x) {
        for (int y = 0; y < no_street; ++y) {
            scanf("%d", &c);
            weight[x][y] = c;
        }
    }

    for (int i = 0; i < no_street; ++i) {
        d.push_back(vertex(i, INFINIY));
    }

    scanf("%d", &no_scenario);
    for (int i = 0; i < no_scenario; ++i) {
        scanf("%d %d %d", &restaurant, &gas_station, &destination);

        // check in cache
        check_in_cache(direct, restaurant, no_street);
        check_in_cache(indirect, gas_station, no_street);

        // calculate the cost
        stop_at_gas_cost = direct[gas_station].cost + indirect[destination].cost;
        direct_cost = direct[destination].cost;

        // output
        display_cost(stop_at_gas_cost, direct_cost);
    }
}

void dijkstra_test(istream& in) {
    int start;
    int no_street;
    int temp[4] = { 0 };
    vector<vertex> path;

    in >> no_street;
    for (int x = 0; x < no_street; ++x) {
        for (int y = 0; y < no_street; ++y) {
            in >> weight[x][y];
        }
    }

    // arrange
    start = 0;
    temp[0] = 0;
    temp[1] = 2;
    temp[2] = 1;
    temp[3] = 3;

    // act
    path = dijkstra_compute_path(start, no_street);

    // assert
    for (int i = 0; i < no_street; ++i) {
        assert(path[i].cost == temp[i]);
    }

    // arrange
    start = 1;
    temp[0] = 1;
    temp[1] = 0;
    temp[2] = 2;
    temp[3] = 4;

    // act
    path = dijkstra_compute_path(start, no_street);

    // assert
    for (int i = 0; i < no_street; ++i) {
        assert(path[i].cost == temp[i]);
    }

    // arrange
    start = 2;
    temp[0] = 2;
    temp[1] = 1;
    temp[2] = 0;
    temp[3] = 3;

    // act
    path = dijkstra_compute_path(start, no_street);
    // assert
    for (int i = 0; i < no_street; ++i) {
        assert(path[i].cost == temp[i]);
    }

    // arrange
    start = 3;
    temp[0] = 1;
    temp[1] = 1;
    temp[2] = 1;
    temp[3] = 0;

    // act
    path = dijkstra_compute_path(start, no_street);
    // assert
    for (int i = 0; i < no_street; ++i) {
        assert(path[i].cost == temp[i]);
    }
}

int main() {
    // ifstream inf("test_data.txt");
    // dijkstra_test(inf);
    inout_delivery_boy();
    return 0;
}
\ifdef\uu GNUC__
#包括
#否则
#包括
#恩迪夫
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#ifdef__GNUC__
名称空间标准{
使用名称空间_gnu_cxx;
}
#恩迪夫
const int MAX_顶点=250;
内部常数=(1 rhs.成本;
}
};
哈希映射缓存;
类型定义优先级\队列最小\ pq;
向量dijkstra_计算_路径(int开始,int n){
min_pq pq;
向量路径;
访问向量(n,0);
int最小成本=0;
综合成本;
顶点u;
对于(int i=0;i更好的成本){
路径[v]。成本=更好的成本;
推送(顶点(v,路径[v]。成本));
}
}
}
}
返回路径;
}
缓存中的无效检查(向量和路径、整数开始、整数否街道){
如果(访问开始[开始]==0){
路径=dijkstra_计算_路径(起点,无_街);
insert(make_pair(start,path));
访问开始[开始]=1;
}
否则{
路径=缓存[开始];
}
}
无效显示成本(内部停止成本、内部气体成本、内部直接成本){
printf(“%d”,以燃气成本停止);
如果(在天然气成本>直接成本时停止){
printf(“%d\n”,停止燃气成本-直接成本);
}
否则{
printf(“0\n”);
}
}
无效句柄\u case\u one(){
int no_情景;
int假人;
int s,g,d;
scanf(“%d”、&dummy);
scanf(“%d”和“无”场景);
对于(int i=0;i>诺乌街;
对于(int x=0;x>重量[x][y]中;
}
}
//安排
开始=0;
温度[0]=0;
温度[1]=2;
温度[2]=1;
温度[3]=3;
//表演
路径=dijkstra_计算_路径(起点,无_街);
//断言
对于(int i=0;i
请注意,问题中的N很小。您是否尝试过Floyd最短路径算法来预先计算每两个节点之间的最短路径?这将花费O(N^3)时间,即问题中的250^3=15625000,应该很容易在1秒内完成运行。然后您可以在O(1)中回答每个查询

弗洛伊德简介:

ps:我认为缓存的dijstra花费了整个测试的最大运行时间O(N^3)