mardi 18 août 2020

Bidirectional A-Star algorithm crash problem

I'm trying to implement the Bidirectional Dijkstra's algorithm with the Eucledean heuristics but when I submit it to the grader it crashes. At first time I was using a set to extract the minimum edge weight and I thought that was the error but I changed for a priority queue and nothing happened. I don't think it crashes because it uses a lot of memory, in the worst case it uses 880000 espaces in memory for the vectors, but maybe I don't know how estimate the amount of memory used in the worst case. Does anyone knows why my code could crash it?

Here is my code:

#include <cstdio>
#include <cassert>
#include <vector>
#include <limits>
#include <utility>
#include <math.h>
#include <queue>
#include <iostream>


using namespace std;

// Vector to represent a graph as an adjacency list
typedef vector<vector<vector<int>>> Adj;

// Distances can grow out of int type
typedef long long Len;

// Vector of two priority_queue - for forward and backward searches.
typedef vector<priority_queue<pair<Len, int>,vector<pair<Len,int>>,greater<pair<Len,int>>>> Queue;
const Len MAX_ = numeric_limits<Len>::max() / 4;

class AStar {
    // Size of the nodes
    int n_;
    // adj_[0] and cost_[0] stores the original edges and its weights
    // adj_[1] and cost_[1] stores the reverses edges and its weights
    Adj adj_;
    Adj cost_;
    // distance_[0] stores the distance for the forward search
    // distance_[1] stores the distance for the backward search
    vector<vector<Len>> distance_;
    // hdistance_[0] stores the distance plus the heuristics value for the forward search
    // hdistance_[1] stores the distance plus the heuristics value for the backward search
    vector<vector<Len>> hdistance_;
    // Stores the nodes discovered in the path neither from source to target or from target to source
    vector<int> workset_;
    // Stores the visited nodes
    vector<bool> visited_;
    // Coordinates of the nodes
    std::vector<std::pair<Len,Len>> xy_;

public:
    AStar(int n, Adj adj, Adj cost, std::vector<std::pair<Len,Len>> xy)
        : n_(n), adj_(adj), cost_(cost), distance_(2, vector<Len>(n_, MAX_)), hdistance_(2, vector<Len>(n_, MAX_)), visited_(n), xy_(xy),workset_(n)
    {}

    // Reset everything
    void clear() {
        for (unsigned int i = 0; i < workset_.size(); ++i) {
            int v = workset_[i];
            visited_[v] = false;
        }
        distance_= vector<vector<Len>>(2, vector<Len>(n_, MAX_));
        hdistance_= vector<vector<Len>>(2, vector<Len>(n_, MAX_));
        workset_.clear();
    }
    // Return the heuristic distance from the node to the target and from the source to the node
    long long potential(int a, int side,int s, int t){
        long long pi_f=sqrt(pow(xy_[a].first-xy_[t].first,2)+pow(xy_[a].second-xy_[t].second,2));
        long long pi_r=sqrt(pow(xy_[s].first-xy_[a].first,2)+pow(xy_[s].second-xy_[a].second,2));
        //cout<<"pi_f="<<pi_f<<", pi_r="<<pi_r<<'\n';
        return side?(pi_r-pi_f)/2:(pi_f-pi_r)/2;
    }

    // Visit each neighbor node and change is distance value if it's needed
    void visit(Queue& q, int side, pair<Len,int> u,int s, int t) {
        for(unsigned int i=0; i<adj_[side][u.second].size();i++){
            int v=adj_[side][u.second][i];
            int w=cost_[side][u.second][i];
            //cout<<"Node -> "<<v<<" ,distance: "<<w<<'\n';
            long long h=potential(v,side,s,t);
            //cout<<"heuristics: "<<h<<'\n';
            //cout<<" - "<<distance_[side][v]<<" "<<distance_[side][u.second]+w<<'\n';
            if((hdistance_[side][v]==MAX_)||(distance_[side][v]>distance_[side][u.second]+w)){
                distance_[side][v]=distance_[side][u.second]+w;
                hdistance_[side][v]=distance_[side][u.second]+w+h;
                q[side].push(make_pair(hdistance_[side][v],v));
            }
        }
        workset_.push_back(u.second);
    }
    // Returns the shortest distance to the target
    Len Shortest_Path() {
        long long distance=MAX_;
        for(unsigned int i=0; i<workset_.size();i++){
            if(distance_[0][workset_[i]]+distance_[1][workset_[i]]<distance){
                distance=distance_[0][workset_[i]]+distance_[1][workset_[i]];
            }
        }
        return distance;
    }
    // Process each query
    Len query(int s, int t) {
        clear();
        Queue q(2);
        q[0].push(make_pair(0,s));
        q[1].push(make_pair(0,t));
        distance_[0][s]=0;
        hdistance_[0][s]=0;
        hdistance_[1][t]=0;
        distance_[1][t]=0;
        pair<Len,int> v;
        do{
            // Forward search
            if(q[0].size()==0){
                break;
            }
            v=q[0].top();
            q[0].pop();
            //If it's a non-updated node
            if(hdistance_[0][v.second]!=v.first){
                continue;
            }
            visit(q,0,v,s,t);
            if(visited_[v.second]==1){
                return Shortest_Path();
            }
            visited_[v.second]=1;

            // Backward search
            if(q[1].size()==0){
                break;
            }
            v=q[1].top();
            q[1].pop();
            //If it's a non-updated node
            if(hdistance_[1][v.second]!=v.first){
                continue;
            }
            visit(q,1,v,s,t);
            if(visited_[v.second]==1){
                return Shortest_Path();
            }
            visited_[v.second]=1;
        }while(true);
        return -1;
    }
};

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    std::vector<std::pair<Len,Len>> xy(n);
    for (unsigned int i=0;i<n;++i){
        int a, b;
        scanf("%d%d", &a, &b);
        xy[i] = make_pair(a,b);
    }
    Adj adj(2, vector<vector<int>>(n));
    Adj cost(2, vector<vector<int>>(n));
    for (unsigned int i=0; i<m; ++i) {
        int u, v, c;
        scanf("%d%d%d", &u, &v, &c);
        adj[0][u-1].push_back(v-1);
        cost[0][u-1].push_back(c);
        adj[1][v-1].push_back(u-1);
        cost[1][v-1].push_back(c);
    }

    AStar astar(n, adj, cost, xy);

    int t;
    scanf("%d", &t);
    for (int i=0; i<t; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        printf("%lld\n", astar.query(u-1, v-1));
    }
}

Here are the constraints:

enter image description here

Aucun commentaire:

Enregistrer un commentaire