3

編集済み - 12/03/12 @ 1:05 AM PST

次のようにコードを編集しました。ただし、まだパスを返すことができません。

繰り返しますが、このコードは、ユーザーが指定した開始頂点と距離を使用してパスを計算するものです。プログラムは、指定されたデータに一致する適切なパスをすべて返します。

これまでの私のコードは次のとおりです。

vector<vector<Vertex>> Graph::FindPaths(Graph &g, int startingIntersection, float distanceInMiles)
{   
/* A vector which contains vectors which will contain all of the suitable found paths. */
vector<vector<Vertex>> paths;

/* Create an empty set to store the visited nodes. */
unordered_set<int> visited;

/* Vector which will be used to the hold the current path. */
vector<Vertex> CurrentPathList;

/* Will be used to store the currerntVertex being examined. */
Vertex currentVertex;

/* Will be used to store the next vertex ID to be evaluated. */
int nextVertex;

/* Will be used to determine the location of the start ID of a vertex within the VertexList. */
int start;

/* Stack containing the current paths. */
stack<Vertex> currentPaths;

/* CurrentPathDistance will be used to determine the currernt distance of the path. */
float currentPathDistance = 0;

/* The startingIntersection location must be found within the VertexList.  This is because there is
 * no guarantee that the VertexList will hold sequential data.
 *
 * For example, the user inputs a startingIntersection of 73.  The Vertex for intersection #73 may 
 * be located at the 20th position of the VertexList (i.e. VertexList[20]). */
start = g.FindStartingIntersection(g, startingIntersection);

/* Push the startingIntersection onto the stack. */
currentPaths.push(g.VertexList[start]);

/* Continue to iterate through the stack until it is empty.  Once it is empty we have exhaused all
 * possible paths. */
while(!currentPaths.empty())
{
    /* Assign the top value of the stack to the currentVertex. */
    currentVertex = currentPaths.top();

    /* Pop the top element off of the stack. */
    currentPaths.pop();

    /* Check to see if we are back to the startingIntersection.  As a note, if we are just starting, it will 
     * put the startingIntersection into the paths. */
    if(currentVertex.id == startingIntersection)
    {
        /* Add currentVertex to a list. */
        CurrentPathList.push_back(currentVertex);

        /* Find the current path distance. */
        currentPathDistance = FindPathDistance(g, CurrentPathList);

        /* Check the currentPathDistance.  If it is within +/- 1 mile of the specified distance, then place
         * it into the vector of possible paths. */
        if((currentPathDistance + 1 >= distanceInMiles) && (currentPathDistance - 1 <= distanceInMiles))
        {
            paths.push_back(CurrentPathList);
        }
    }
    else /* The ending vertex was not the user specified starting vertex. */
    {
        /* Remove all elements from the stack. */
        while(!currentPaths.empty())
        {
            currentPaths.pop();
        }
    }

    nextVertex = FindUnvisitedNeighbor(g, currentVertex, visited);

    // repeat while current has unvisited neighbors
    while(nextVertex != -1)
    {
        /* Find the new starting vertex. */
        start = g.FindStartingIntersection(g, nextVertex);

        /* Push the startingIntersection onto the stack. */
        currentPaths.push(g.VertexList[start]);

        /* Push the next vertex into the visted list. */
        visited.insert(nextVertex);

        nextVertex = FindUnvisitedNeighbor(g, currentVertex, visited);
    }     
}

/* Return the vector of paths that meet the criteria specified by the user. */
return paths;

私のコードFindingUnvistedNeighbor()は次のとおりです。

int FindUnvisitedNeighbor(Graph &g, Vertex v, unordered_set<int> visited)
{
    /* Traverse through vertex "v"'s EdgeList. */
    for(int i = 0; i + 1 <= v.EdgeList.size(); i++)
    {
        /* Create interator to traverse through the visited list to find a specified vertex. */
        unordered_set<int>::const_iterator got = visited.find(v.EdgeList[i].intersection_ID_second);

        /* The vertex was not found in the visited list. */
        if(got == visited.end())
        {

            return v.EdgeList[i].intersection_ID_second;
        }
    }

    return -1;
}
4

2 に答える 2

0

深さ優先で大丈夫です。中止する必要がある場合

* path too long (bad)
* vertex already visited (bad)
* starting vertex visited (found a solution)

これらの条件を検出するには、これまでに訪問したエッジ/頂点を追跡する必要があります

深さの最初の歩行は、この(完全にチェックされていない)疑似コードのように見え
ますとにかく、アイデアを得る必要があります

edge
    pair of node
    length

node
    list of edge

arrow               // incoming edge, node
    pair of edge, node

path
    list of arrow



check_node(arrow)   // incoming edge, node
    current_path.push(arrow)
    if length(current_path) > limit
        // abort too long
        current_path.pop(arrow)
        return
    if length(current_path) > 0 && current_path.first.node == current_path.last,node
        // found solution
        solutions.push(current_path)  // store the found solution and continue search
        current_path.pop(arrow)
        return
    if node in current_path
        // abort cycle
        current_path.pop(arrow)
        return
    for each edge in node
        // go deeper
        check(arrow(edge, edge.other_node))
    current_path.pop(arrow)
    return


main
    path current_path
    list of path solutions    // will hold all possible solutions after the check

    make_graph

    check_node(NULL, graph.start)

    for each solution in solutions   // print 0 .. n solutions
        print solution
于 2012-12-02T10:54:22.357 に答える
0

これは、実装固有の問題ではなく、基本的なアルゴリズムの問​​題のように思われるため、実際のコードではなく、アルゴリズムの詳細で高レベルの疑似コードを提供しました。また、私はC++を知りません。構文/ロジックが不明な場合はお知らせください。さらに明確にすることができます。基本的に DFS を実行しますが、値が見つかっても停止しません。検索を続行し、値へのすべてのパス (指定された距離基準を満たす) を報告します。

// Input: Graph G, Vertex start, Integer targetDistance
// Output: Set< List<Vertex> > paths
FindPaths ( G, start, targetDistance ):
    create an empty set, paths
    create an empty set, visited
    create an empty stack, currentPath

    // Iterative Exhaustive DFS
    push start on currentPath
    while ( currentPath is not empty ):
        current = pop ( currentPath )

        if ( current equals start ):
            copy currentPath to a list, L (reversed order doesn't matter)
            // find its weight
            w = FindPathWeight ( L, G )

            if ( w+1 >= targetDistance AND w-1 <= targetDistance ):
                add L to paths

        else if ( current is a dead-end ): drop it completely, it's useless

        x = FindUnvisitedNeighbor ( current, G, visited )
        // repeat while current has unvisited neighbors
        while ( x ):
            push x on currentPath
            add x to visited
            x = FindUnvisitedNeighbor ( current, G, visited )

    return paths
//EndFindPaths


// Input: List path, Graph G
// Output: Integer weight
FindPathWeight ( path, G ):
    Integer weight = 0;

    for each ( Vertex v in path ):

        if ( v is the end of the path ): break

        Consider the next vertex in the list, u
        Find the edge v——u in the graph, call it e
        Get the weight of e, w
        weight = weight + w

    return weight
//EndFindPathWeight


// Input: Vertex v, Graph G, Set visited
// Output: Vertex u (or null, if there are none)
FindUnvisitedNeighbor ( v, G, visited ):

    for each ( Edge v——u in G.EdgeList ):

        if ( u in visited ): continue

        // u is the first unvisited neighbor
        return u

    return null
//EndFindUnvisitedNeighbor
于 2012-12-02T13:02:26.187 に答える