[算法]分支定界法——单源最短路径

某公司於乙城市的销售点急需一批成品,该公司成品生产基地在甲城市。
甲城市与乙城市之间共有 n 座城市,互相以公路连通。甲城市、乙城市以及其它各城市之间的公路连通情况及每段公路的长度由矩阵M1 给出。
每段公路均由地方政府收取不同额度的养路费等费用,具体数额由矩阵M2 给出。
请给出在需付养路费总额不超过 1500 的情况下,该公司货车运送其产品从甲城市到乙城市的最短运送路线。
具体数据参见文件:
M1.txt: 各城市之间的公路连通情况及每段公路的长度矩阵(有向图); 甲城市为城市Num.1,乙城市为城市Num.50。M2.txt: 每段公路收取的费用矩阵(非对称)。

#include<stdio.h>
#define UNREACHABLE     9999
#define NODENUM         50
#define MAXCOST         1500
#define LENTHFILE       "m1.txt"
#define COSTFILE        "m2.txt"
typedef struct
{
    int nodeNum;
    int currentLength;
    int currentCost;
}NodeInfo;
void pushHeap(NodeInfo *minRootHeap, NodeInfo newNode, int *length);
NodeInfo popHeap(NodeInfo *minRootHeap, int *length);
void adjustHeap(NodeInfo *minRootHeap, int *length);
void sub_adjustHeap(NodeInfo *minRootHeap, int adjustLoc, int *length);
int shortestPath(int nodeDist[][NODENUM], int roadCost[][NODENUM], int *prev);
void read(int input[][NODENUM], char *filename);
void print(int *prev, int location);
int main()
{
    int nodeMap[NODENUM][NODENUM], costMap[NODENUM][NODENUM], prev[NODENUM], pathLength;
    read(nodeMap, LENTHFILE);
    read(costMap, COSTFILE);
    pathLength = shortestPath(nodeMap, costMap, prev);
    if(pathLength)
    {
        printf("the shortest distence is:%d\n", pathLength);
        printf("the order is: ");
        print(prev, NODENUM - 1);
        printf("\n");
    }
    else
    {
        printf("there is not any path supported\n");
    }
    return 0;
}
int shortestPath(int nodeDist[][NODENUM], int roadCost[][NODENUM], int *prev)
{
    NodeInfo minRootHeap[NODENUM], activeNode, newNode;
    int nodeQuantity = 0, distance[NODENUM] = {0}, i;
    prev[0] = -1;
    newNode.currentCost = 0; newNode.currentLength = 0; newNode.nodeNum = 0;
    pushHeap(minRootHeap, newNode, &nodeQuantity);
    do
    {
        activeNode = popHeap(minRootHeap, &nodeQuantity);
        for(i = 0; i < NODENUM; i++)
        {
            if(nodeDist[activeNode.nodeNum][i] != UNREACHABLE)
            {
                newNode.nodeNum = i;
                newNode.currentLength = activeNode.currentLength + nodeDist[activeNode.nodeNum][i];
                newNode.currentCost = activeNode.currentCost + roadCost[activeNode.nodeNum][i];
                if(newNode.currentCost <= MAXCOST &&
                    (!distance[newNode.nodeNum] || newNode.currentLength < distance[newNode.nodeNum]))
                {
                    pushHeap(minRootHeap, newNode, &nodeQuantity);
                    distance[newNode.nodeNum] = newNode.currentLength;
                    prev[newNode.nodeNum] = activeNode.nodeNum;
                }
            }
        }
    }while(nodeQuantity);
    return distance[NODENUM - 1];
}
void pushHeap(NodeInfo *minRootHeap, NodeInfo newNode, int *length)
{
    minRootHeap[*length] = newNode;
    (*length)++;
    adjustHeap(minRootHeap, length);
}
NodeInfo popHeap(NodeInfo *minRootHeap, int *length)
{
    NodeInfo minNode = minRootHeap[0];
    (*length)--;
    minRootHeap[0] = minRootHeap[*length];
    sub_adjustHeap(minRootHeap, 0, length);
    return minNode;
}
void adjustHeap(NodeInfo *minRootHeap, int *length)
{
    int location = (*length - 1) / 2;
    while(location >= 0)
    {
        sub_adjustHeap(minRootHeap, location, length);
        location--;
    }
}
void sub_adjustHeap(NodeInfo *minRootHeap, int adjustLoc, int *length)
{
    NodeInfo tempNode = minRootHeap[adjustLoc];
    int child = 2 * adjustLoc + 1;
    while(child < (*length))
    {
        if(child < (*length - 1) &&
            minRootHeap[child].currentLength > minRootHeap[child + 1].currentLength)
        {
            child++;
        }
        if(tempNode.currentLength < minRootHeap[child].currentLength)
        {
            break;
        }
        minRootHeap[(child - 1) / 2] = minRootHeap[child];
        child = 2 * child + 1;
    }
    minRootHeap[(child - 1) / 2] = tempNode;
}
void read(int input[][NODENUM], char *filename)
{
    int i, j;
    FILE *fin;
    char ch;
    fin = fopen(filename, "r");
    for(i = 0; i < NODENUM; i++)
    {
        for(j = 0; j < NODENUM; j++)
        {
            fscanf(fin, "%d", &input[i][j]);
        }
    }
}
void print(int *prev, int location)
{
    if(prev[location] == -1)
    {
        printf("%d ", location);
        return;
    }
    print(prev, prev[location]);
    printf("%d ", location);
}

点赞