华为codecraft算法大赛---寻路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sb19931201/article/details/52496925

华为codecraft算法大赛—寻路

前言

最近实验室的师兄师姐们在热火朝天的笔试(都说难难难),我也要了些题来感受了一下,已然被虐的体无完肤。选择题考的内容涉及范围广,算法编程题对于没有刷题经验的我来说就更是难上加难了。看来有必要在学习工作之余学习学习算法以及计算机基础知识了。

翻了上半年参加华为codecraft算法大赛的代码,趁周末整理一下当时的思路以及回顾一下数据结构与算法。比赛前中期还保持不错的名次,一直维持在二十名左右以为稳稳三十二强了,结果后期突破不大,最后几天呼呼的被超过,真是太天真了。后来回想确实方法思路比较死板,一口咬定DFS+剪枝,没有去尝试新的算法如A*,模拟退火算法等,还有大赛群里分享说的动态规划、数模等。

比赛源码以及样例数据在我的github:
https://github.com/hczheng/2016Codecraft

赛题介绍

1 问题定义
给定一个带权重的有向图G=(V,E),V为顶点集,E为有向边集,每一条有向边均有一个权重。对于给定的顶点s、t,以及V的子集V’,寻找从s到t的不成环有向路径P,使得P经过V’中所有的顶点(对经过V’中节点的顺序不做要求)。
若不存在这样的有向路径P,则输出无解,程序运行时间越短,则视为结果越优;若存在这样的有向路径P,则输出所得到的路径,路径的权重越小,则视为结果越优,在输出路径权重一样的前提下,程序运行时间越短,则视为结果越优。
说明:
1)图中所有权重均为[1,20]内的整数;
2)任一有向边的起点不等于终点;
3)连接顶点A至顶点B的有向边可能超过一条,其权重可能一样,也可能不一样;
4)该有向图的顶点不会超过600个,每个顶点出度(以该点为起点的有向边的数量)不超过8;
5)V’中元素个数不超过50;
6)从s到t的不成环有向路径P是指,P为由一系列有向边组成的从s至t的有向连通路径,且不允许重复经过任一节点;
7)路径的权重是指所有组成该路径的所有有向边的权重之和。

2 输入与输出
输入文件格式
以两个.csv 文件(csv 是以逗号为分隔符的文本文件)给出输入数据,一个为图的数据(G),一个为需要计算的路径信息(s,t,V’)。文件每行以换行符(ASCII’\n’即0x0a)为结尾。

1)图的数据中,每一行包含如下的信息:
LinkID,SourceID,DestinationID,Cost
其中,LinkID 为该有向边的索引,SourceID 为该有向边的起始顶点的索引,DestinationID为该有向边的终止顶点的索引,Cost 为该有向边的权重。顶点与有向边的索引均从0 开始 编号(不一定连续,但用例保证索引不重复)。
2)路径信息中,只有一行如下数据:
SourceID,DestinationID,IncludingSet
其中,SourceID 为该路径的起点,DestinationID 为该路径的终点,IncludingSet 表示必须经过的顶点集合V’,其中不同的顶点索引之间用’|’分割。
输出文件格式
输出文件同样为一个.csv 文件。
1)如果该测试用例存在满足要求的有向路径P,则按P 经过的有向边顺序,依次输出有向边的索引,索引之间用’|’分割;
2)如果该测试用例不存在满足要求的有向路径P,则输出两个字符NA;
3)只允许输出最多一条有向路径。

3.简单用例说明

赛题思路

我当时第一反应就是最短路径算法,但是直接套用过来是肯定不行的,因为最短路径算法(dijkstra)是一层一层往外扩,然后利用贪心算法的思想得到每一层级的最优路径。二本赛题加了必过点的限制,因此需要对算法进行改造,为了能得到赛题结果,在一步步改造的过程中发现已经抛弃了贪心算法思想,最后渐渐的升级深度优先遍历(DFS)的基本思想,但是记录每一步遍历的顺序,方便回溯(在找到可行解的基础上还要考虑最优解)。随着比赛的进行,赛题数据复杂度的增加,回溯版DFS不能在有效的时间内得到最优解,甚至不能得到一个可行解。因此我又在该基础上增加了”剪枝”的思想,就是剪断一些出度较大的节点的路径,这样可以降低复杂度,并且能得到不错的结果,“剪枝”的尺度与位置其实是随机(缺乏科学性)的,由于是比赛,所以可以通过评分程序去修改算法拟合赛题数据。也是因为这种小聪明导致我这次比赛前中期效果不错,后期却非常乏力。这是应该吸取的教训,还是应该从算法本身的有效性入手,那样才会有真正的提高。

以下是输入数据以及输出结果样例



比赛源码

比赛要求的编译环境是Linux+gcc;为了方便调试,以下代码(已带详细注释)是Windows+Visual Stdio下的,有兴趣可以自行转换,也可以在以下地址下载提交版(包括华为官方提供的编译脚本)。

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fstream> 
using namespace std;

#define PRINT  printf
#define MAX_RECORD  100
#define MAX_LINE_LEN 4000
#define Error( Str )   FatalError( Str )
#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )
//邻接表读图,
//前面这些把图读进邻接表,
typedef struct ListNode *Position;//位置
typedef Position List;//链表
typedef struct Tbl *Table;//邻接表
typedef int ElementType;
typedef int Vertex;//顶点
typedef struct VertexTable *VerTable;//例子4个顶点
#define Infinity 65536 //各个顶点初始化
#define NotAVertex -1
#define nowstart 0//当前起点,初始化为0
#define NotFound -1//折半查找
#define LeftChild(i) (2*(i)+1)//堆排序                         
typedef struct StackRecord *Stack;
#define EmptyTOS -1

//*************************************读文件********************************************//

int read_file(char ** const buff, const unsigned int spec, const char * const filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp == NULL)
    {
        PRINT("Fail to open file %s, %s.\n", filename, strerror(errno));
        return 0;
    }
    PRINT("Open file %s OK.\n", filename);

    char line[MAX_LINE_LEN + 2];
    unsigned int cnt = 0;
    while ((cnt < spec) && !feof(fp))
    {
        line[0] = 0;
        fgets(line, MAX_LINE_LEN + 2, fp);
        if (line[0] == 0)   continue;
        buff[cnt] = (char *)malloc(MAX_LINE_LEN + 2);
        strncpy(buff[cnt], line, MAX_LINE_LEN + 2 - 1);
        buff[cnt][4001] = 0;
        cnt++;
    }
    fclose(fp);
    PRINT("There are %d lines in file %s.\n", cnt, filename);
    return cnt;
}

//*************************************基本数据结构********************************************//

struct StackRecord
{
    int Capacity;
    int TopOfStack;
    ElementType *Array;
};
////创建栈
Stack CreateStack(int MaxElements)
{
    Stack S;
    S = (struct StackRecord*)malloc(sizeof(struct StackRecord));
    if (S == NULL)
        FatalError("Out of space!!!");
    S->Array = (int*)malloc(sizeof(ElementType)*MaxElements);
    if (S->Array == NULL)
        FatalError("Out of space!!!");
    S->Capacity = MaxElements;
    S->TopOfStack = EmptyTOS;
    return S;
}
//出栈
void Pop(Stack S)
{
    if (S->TopOfStack == EmptyTOS)
        Error("Empty Stack");
    else
        S->TopOfStack--;
}
//入栈
void Push(ElementType X, Stack S)
{
    if (S->TopOfStack == S->Capacity - 1)
        Error("Full stack");
    else
        S->Array[++S->TopOfStack] = X;
}
//销毁栈
void DisposeStack(Stack S)
{
    if (S != NULL)
    {
        free(S->Array);
        free(S);
    }
}
ElementType Top(Stack S)
{
    if (S->TopOfStack != EmptyTOS)
    {
        return S->Array[S->TopOfStack];
    }
    else
    {
        Error("Empty Stack");
        return 0;
    }
}
//链表,每个存储了顶点Element,权重Cost,指向下一个的Next;
struct ListNode
{
    ElementType ELement;
    int Cost;
    int Priority;
    int Edge;
    Position Next;
};//0->1,1   Element=1,cost=1;

  //邻接表
struct Tbl
{
    int TableSize;
    List *TheLists;
};

//顶点表
struct VertexTable
{
    int known;
    int Dist;
    Vertex Path;
};

//*************************************邻接表初始化******************************************//

Table InitializeTable(int TableSize)
{
    Table T;
    int i;
    T = (struct Tbl*)malloc(sizeof(struct Tbl));
    if (T == NULL)
        FatalError("Out of space!!!");
    T->TableSize = TableSize;
    T->TheLists = (struct ListNode**)malloc(sizeof(List)*T->TableSize);
    for (i = 0;i<T->TableSize;i++)
    {
        T->TheLists[i] = (struct ListNode*)malloc(sizeof(struct ListNode));
        if (T->TheLists[i] == NULL)
            FatalError("Out of space!!!");
        else
            T->TheLists[i]->Next = NULL;
    }
    return T;
}

//*************************************链表插入********************************************//

void Insert(int Edge, ElementType Pos, ElementType Key, ElementType Cost, ElementType Priority, Table T)
{
    Position NewCell;
    List L;
    NewCell = (struct ListNode*)malloc(sizeof(struct ListNode));
    if (NewCell == NULL)
        FatalError("Out of space!!!");
    else
    {
        L = T->TheLists[Pos];
        NewCell->Next = L->Next;
        NewCell->Edge = Edge;
        NewCell->ELement = Key;
        NewCell->Cost = Cost;
        NewCell->Priority = Priority;
        L->Next = NewCell;
    }
}

//*************************************顶点表初始化*****************************************//

VerTable InitialWeighted(Vertex Start, VerTable V, int NumVertex)//V为顶点集合,每隔顶点有三种标记
{
    int i;
    V = (struct VertexTable*)malloc(sizeof(struct VertexTable)*NumVertex);
    for (i = 0;i<NumVertex;i++)
    {
        V[i].known = 0;
        V[i].Dist = 0;
        V[i].Path = NotAVertex;
    }
    V[Start].Dist = 0;
    return V;
}

//*************************************二分查找********************************************//

int BinarySearch(const ElementType A[], ElementType X, int N)
{
    int Low, Mid, High;
    Low = 0;High = N - 1;
    while (Low <= High)
    {
        Mid = (Low + High) / 2;
        if (A[Mid]<X)
            Low = Mid + 1;
        else
            if (A[Mid]>X)
                High = Mid - 1;
            else
                return Mid;
    }
    return NotFound;
}

void MakeEmpty(List L)
{
    Position P, Tmp;
    P = L->Next;
    L->Next = NULL;
    while (P != NULL)
    {
        Tmp = P->Next;
        free(P);
        P = Tmp;
    }
}
void Disposable(Table T)
{
    int i;
    for (i = 0;i<T->TableSize;i++)
    {
        MakeEmpty(T->TheLists[i]);
    }
    free(T->TheLists);
    free(T);
}

//*************************************堆排序********************************************//

void PercDown(ElementType A[], int i, int N)
{
    int Child;
    ElementType Tmp;
    for (Tmp = A[i];LeftChild(i)<N;i = Child)
    {
        Child = LeftChild(i);
        if (Child != N - 1 && A[Child + 1]>A[Child])
            Child++;
        if (Tmp<A[Child])
            A[i] = A[Child];
        else
            break;
    }
    A[i] = Tmp;
}
void Swap(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
void Heapsort(ElementType A[], int N)
{
    int i;
    for (i = N / 2;i >= 0;i--)
        PercDown(A, i, N);
    for (i = N - 1;i>0;i--)
    {
        Swap(&A[0], &A[i]);
        PercDown(A, 0, i);
    }
}

//*************************************打印路径********************************************//

void PrintPath(Vertex Ver, VerTable V, int C[])
{
    if (V[Ver].Path != NotAVertex)
    {
        PrintPath(V[Ver].Path, V, C);
        printf("->");
    }
    printf("%d", C[Ver]);
}

//************************************输出边编号*******************************************//

int find_route(int stop, Table T, VerTable V)
{
    Position Tmp;
    int result = -1;
    Tmp = T->TheLists[V[stop].Path]->Next;//
    while (Tmp != NULL)
    {
        if (Tmp->ELement == stop) { result = Tmp->Edge;break; }
        Tmp = Tmp->Next;
    }
    return result;
}

///*************************************重复边处理****************************************//

Position FindPrevious(ElementType X, List L)
{
    Position P;

    P = L;
    while (P->Next != NULL && P->Next->ELement != X)
        P = P->Next;

    return P;
}
int IsLast(Position P, List L)
{
    return P->Next == NULL;
}

void Delete(ElementType X, List L)
{
    Position P, TmpCell;

    P = FindPrevious(X, L);

    if (!IsLast(P, L))  /* Assumption of header use */
    {                      /* X is found; delete it */
        TmpCell = P->Next;
        P->Next = TmpCell->Next;  /* Bypass deleted cell */
        free(TmpCell);
    }
}
Position Find(ElementType X, List L)
{
    Position P;
          P = L->Next;
          while (P != NULL && P->ELement != X)
           P = P->Next;
          return P;
}

///*******************************/自定义查找下一顶点的算法*************************************//

int find_start(VerTable V, Table T, ElementType demand[], int start_now, int known_p, int end, Stack S, int N)
{
    //传入的参数分别为:顶点表(konwn,dis,path)、优先点集、当前遍历起点
    //返回值为下一个起点索引TempV,以及特征点入栈
    Position tmp;
    int min = Infinity;//普通点最小权值
    int min_sp = Infinity;//优先点最小权值
    int count_sp = 0;//优先点计数(用于判断特征点)
    int count_normal = 0;//普通点计数
    int normal[8] = { 0 };//普通点数组(暂存)
    int special[8] = { 0 };//优先点数组(暂存)
    Vertex TempV = -1;//开始标记
    int flag = 0;//终点标记
                 //TMP = T->TheLists[start_now];
    tmp = T->TheLists[start_now]->Next;
    while (tmp != NULL) //0->3->1->NULL  还有邻接点且未到达过
    {
        if (V[tmp->ELement].known != 1) {
            if (tmp->Priority == 1)//如果该顶点是优先点
            {
                count_sp++;//当前层级优先点数+1
                if (tmp->Cost < min_sp) //当前点权值更小
                {
                    if (count_sp > 1)
                    {
                        special[count_sp - 2] = TempV;
                        V[TempV].Dist = 0;
                    }
                    min_sp = tmp->Cost;//更新min_sp                   
                    TempV = tmp->ELement;//返回值
                    V[TempV].Dist = V[start_now].Dist + tmp->Cost;
                }
                else
                {
                    if (count_sp > 1)
                    {
                        special[count_sp - 2] = tmp->ELement;;
                    }
                }
            }
            else if (tmp->ELement == end)//如果该顶点是终点
            {
                flag = 1;//表明这一轮有终点,但暂时不作处理
                V[end].Dist = V[start_now].Dist + tmp->Cost;
                V[end].Path = start_now;
            }
            else //如果该顶点是普通点
            {
                count_normal++;//普通点计数
                normal[count_normal - 1] = tmp->ELement;//普通点暂存
                if (count_sp == 0 && tmp->Cost < min)//(1.有普通点没有终点没有优先点2.有普通点有终点没有优先点)
                {
                    min = tmp->Cost;//更新min
                    V[TempV].Dist = 0;
                    TempV = tmp->ELement;//返回值  
                    V[TempV].Dist = V[start_now].Dist + tmp->Cost;
                }
            }
        }
        tmp = tmp->Next;
    }
    ///////////*************************LOOK***************************///////////////
    if (count_sp == 0) //假如没有优先点,则把多余的普通点全部入栈
    {
        for (int i = 0;i < count_normal;i++)
        {
            if (TempV != normal[i])
            {
                Push(normal[i], S);Push(start_now, S);//V[normal[i]].Path = start_now;
            }
        }//普通点分支入栈      
    }
    else//当优先点数>=1时
    {
        if (count_sp == 1)//假如刚好只有一个优先点,那么普通点入栈,并赋值path
        {
            for (int i = 0;i < count_normal;i++) { Push(normal[i], S); Push(start_now, S); }//V[normal[i]].Path = start_now;
        }
        else//当优先点数大于1时,普通点先全部入栈,然后多余的优先点入栈
        {
            for (int i = 0;i < count_normal;i++) { Push(normal[i], S); Push(start_now, S); } //V[normal[i]].Path = start_now;
            for (int i = 0;i < count_sp - 1;i++) { Push(special[i], S);Push(start_now, S); }//V[special[i]].Path = start_now;
        }
    }
    if (flag == 1 && known_p == N)//已到终点,且这一层没有优先点了,就要判断是否已经结束(优先点已全部在路径中)
    {
        TempV = 10000; //10000结束标志,到达终点且所有的优先点已在路径中
    }
    if (TempV == -1) { TempV = -start_now; if (start_now == 0) { TempV = -1000; } }//返回停止点(带负号,方便处理)
    if (TempV != 10000 && TempV >= 0) { V[TempV].Path = start_now; }
    return TempV;//返回下一起点索引
}

//**************************************核心查找算法********************************************//

int DF(VerTable V, Table T, ElementType demand[], Stack S, int N, int start_now, int end, unsigned short *result,int big)
{
    //Vertex Ver, W;//顶点索引
    Position Tmp;
    //int end = 5;//假定一个终点
    int startone=start_now ;//存起点
    int known_p = 0;//记录已到过的优先点
    int flag = 0;//遍历过优先点标记
    int min_dist = 10000;
    int ok = 0;
    for (;;)
    {
        if (start_now == 10000)//当前起点为10000,查找成功
        {
            flag++;//迭代次数
            if (min_dist > V[end].Dist)
            {
                int tmp = end;
                int count = 0;
                while (tmp != startone)
                {
                   result[count] = find_route(tmp, T, V);
                   count++;
                   ok = count;
                   tmp = V[tmp].Path;
                }
                min_dist = V[end].Dist;
            }
            else V[end].Dist = min_dist; 
            if (S->TopOfStack == -1||flag>10) break;
                printf("flag:%d\n",flag);           
                //if (big>7&&big<30)break;
                //if (big>150 && big<200&&flag>7)break;
                //if (big>200 && big<250 && flag>3)break;
                if (big>250&&flag>0)break;
                int pass = Top(S);//获得特征点索引 0->1->3                 
                Pop(S);//出栈
                start_now = Top(S);//将当前起点改为栈顶元素        
                int stop = V[end].Path;//继续回溯
                while (stop != pass)
                {
                    V[stop].known = 0;
                    if (BinarySearch(demand, stop, N) >= 0) { known_p--; }
                    stop = V[stop].Path;
                }
                Pop(S);//出栈 
                /*if (S->TopOfStack != -1) {
                    if (big> 150&&big<200) { Pop(S);Pop(S); }//边数在
                    if (big> 200 && big<250) { Pop(S);Pop(S);Pop(S);Pop(S); }//边数在200-250,一次剪断两条边
                    if (big> 250) { Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);Pop(S); }//边数大于250,一次剪断三条边*/
                //剪枝操作
                V[start_now].Path = pass;//出栈起点路径信息
                Tmp = T->TheLists[pass]->Next;
                while (Tmp != NULL)
                {
                    if (Tmp->ELement == start_now) { V[start_now].Dist = V[pass].Dist + Tmp->Cost; }
                    Tmp = Tmp->Next;
                }
        }       
        if (start_now < 0 && S->TopOfStack == -1) break; //栈空,则返回无解
        if (start_now <0)//回头
        {
            int stop = -start_now;//停止点
            if (start_now == -1000) { stop = 0; }//0为停止点的情况
            int pass = Top(S);//获得特征点索引 0->1->3                 
            Pop(S);//出栈
            //printf("%d出栈:\n", pass);
            start_now = Top(S);//将当前起点改为栈顶元素            
            while (stop != pass)
            {
                V[stop].known = 0;
                if (BinarySearch(demand, stop, N) >= 0) { known_p--; }
                //printf("%d回撤:\n", stop);
                stop = V[stop].Path;
                //V[stop].Path = NotAVertex;
            }
            Pop(S);//出栈 
            //printf("%d出栈:\n", start_now);
            if (S->TopOfStack != -1) {
                //if (big>150 && big < 200) { Pop(S);Pop(S);}//边数在150-200之间,一次剪断一条边
                if (big> 100&&big<250) { Pop(S);Pop(S);Pop(S);Pop(S); }//边数在200-250,一次剪断两条边
                if (big> 250) { Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);Pop(S);}//边数大于250,一次剪断三条边
            }//剪枝操作
            V[start_now].Path = pass;//出栈起点路径信息
            Tmp = T->TheLists[pass]->Next;
            while (Tmp != NULL)
            {
                if (Tmp->ELement == start_now) { V[start_now].Dist = V[pass].Dist + Tmp->Cost; }
                Tmp = Tmp->Next;
            }
        }
        V[start_now].known = 1;//将当前起点标记为已知
        if (BinarySearch(demand, start_now, N) >= 0) { known_p++; }//记录到达的优先点数
        start_now = find_start(V, T, demand, start_now, known_p, end, S, N);//按自定义方法找下一个起点
        printf("当前点:%d\n",start_now);
    }
    return ok;
}

//**************************************调用算法********************************************//

void search_route(char *graph[5000], int edge_num, char *condition)//字符串数组(topo),行数,字符串(demand)
{
    Table T = InitializeTable(600);//顶点
    VerTable V = NULL;
    Stack S = CreateStack(1000);//创建栈(存分支点)
    unsigned short result[100] = { -1 };//示例中的一个解 
    const int n = edge_num;
    int  N, start_now, end, demand[100] = { -1 }, test[400][4] = { 0 };
    char *save_ptr, *line;//存剩余的
    for (int i = 0;i<n;i++)//test初始化
    {
        char *hello = graph[i];
        char *p, *token;
        int j = 0;
        for (p = hello; ; p = NULL, j++)
        {
            token = strtok_s(p, ",", &save_ptr);
            if (NULL == token)   break;
            test[i][j] = atoi(token);
        }
    }
    start_now = atoi(strtok_s(condition, ",", &save_ptr));//起点
    printf("start_now=%d \n", start_now);
    end = atoi(strtok_s(NULL, ",", &save_ptr));//终点
    printf("end=%d \n", end);
    line = strtok_s(NULL, ",", &save_ptr);//优先点字符串
    printf("special_line=%s \n", line);
    char *get, *token;
    save_ptr = NULL;
    int d_count = 0;
    for (get = line; ; get = NULL, d_count++)
    {
        token = strtok_s(get, "|", &save_ptr);
        if (NULL == token)   break;
        demand[d_count] = atoi(token);
        // printf("demand[%d]=%d \n",d_count,demand[d_count]);
    }
    N = d_count;
    int Sort[400 * 2] = { -1 }, Max, *C, p = 0, Stemp, Etemp, *Fdemand;
    for (int i = 0; i < n; i++)
    {
        Sort[2 * i] = test[i][1];
        Sort[2 * i + 1] = test[i][2];
    }//把起点和终点包含的点都算进来
    Heapsort(Sort, n * 2);//对顶点进行排序
    Max = Sort[2 * n - 1];
    C = (int*)malloc(sizeof(int)*(Max + 1));
    if (NULL == C)
    {
        FatalError("Out of space!!!");
    }
    for (int i = 0;i<2 * n;i++)
    {
        if (Sort[i] != Sort[i + 1])
        {
            C[p] = Sort[i];
            p++;
        }
    }
    printf("edge_num=%d \n", n);
    printf("point_num=%d \n", p);
    printf("special_num=%d \n", N);
    Fdemand = (int*)malloc(sizeof(int)*(N));;
    for (int i = 0;i<N;i++)
    {
        Stemp = BinarySearch(C, demand[i], p);
        Fdemand[i] = Stemp;
    }
    Heapsort(Fdemand, N);
    Position Pos,L;
    /*for (int j = 0;j<n;j++)//邻接表插入
    {
        Stemp = BinarySearch(C, test[j][1], p);
        Etemp = BinarySearch(C, test[j][2], p);
        if (BinarySearch(Fdemand, Etemp, N) >= 0)
        {
            Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);//start,stop,cost,List,把3必过点插入
            T->TheLists[Stemp]->ELement++;//有几个优先级的点
        }
        else
        {
            Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);//start,stop,cost,List,把3必过点插入
            T->TheLists[Stemp]->ELement++;//有几个优先级的点
        }
    }*/
////////////////////////////////////////////////////
    for (int j = 0;j<n;j++)
    {
        Stemp = BinarySearch(C, test[j][1], p);
        Etemp = BinarySearch(C, test[j][2], p);
        if (BinarySearch(Fdemand, Etemp, N) >= 0)
        {
            L = T->TheLists[Stemp];
            Pos = Find(Etemp, L);
            if (NULL == Pos)
            {
                Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);//start,stop,cost,List,把3必过点插入
                T->TheLists[Stemp]->ELement++;//有几个优先级的点
            }
            else
            {
                if (Pos->Cost > test[j][3])
                {
                    Delete(Pos->ELement, L);
                    T->TheLists[Stemp]->ELement--;//有几个优先级的点
                    Insert(test[j][0], Stemp, Etemp, test[j][3], 1, T);
                    T->TheLists[Stemp]->ELement++;//有几个优先级的点
                }
            }
        }
        else
        {
            L = T->TheLists[Stemp];
            Pos = Find(Etemp, L);
            if (NULL == Pos)
            {
                Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);
                T->TheLists[Stemp]->ELement++;//有几个优先级的点
            }
            else
            {
                if (Pos->Cost > test[j][3])
                {
                    Delete(Pos->ELement, L);
                    T->TheLists[Stemp]->ELement--;//有几个优先级的点
                    Insert(test[j][0], Stemp, Etemp, test[j][3], 0, T);//start,stop,cost,List,把3必过点插入
                    T->TheLists[Stemp]->ELement++;//有几个优先级的点
                }
            }

        }
    }

////////////////////////////////////////////////////
    start_now = BinarySearch(C, start_now, p);
    end = BinarySearch(C, end, p);
    V = InitialWeighted(0, V, n);
    int route = DF(V, T, Fdemand, S, N, start_now, end, result,n);//最短路径D算法     
    int tmp = end;
    int result_count = route;//解的个数
    if (route == 0) { printf("NA\n"); }
    else
    {
        /*if (N>=16) {
        result_count =0;
        while (tmp != start_now)
        {
            result[result_count] = find_route(tmp, T, V);
            result_count++;
            tmp = V[tmp].Path;
        }
        }*/
        PrintPath(end, V, C);
        printf(" COST=%4d\n", V[end].Dist);
        for (int i = result_count - 1;i >= 0;i--)
        {
            printf("%d | ", result[i]);
            //record_result(result[i]);
        }
        printf("\n");
    }
    Disposable(T);
    DisposeStack(S);
    free(V);
    free(C);
    free(Fdemand);
    //record_result(result[i]);
}

int main()
{
    char *topo[5000];
    int edge_num;
    char *demand;
    int demand_num;
    edge_num = read_file(topo, 5000, "topo.csv");
    demand_num = read_file(&demand, 1, "demand.csv");
    search_route(topo, edge_num, demand);
    getchar();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sb19931201/article/details/52496925
今日推荐