華為codecraft演算法大賽---尋路
華為codecraft演算法大賽—尋路
前言
最近實驗室的師兄師姐們在熱火朝天的筆試(都說難難難),我也要了些題來感受了一下,已然被虐的體無完膚。選擇題考的內容涉及範圍廣,演算法程式設計題對於沒有刷題經驗的我來說就更是難上加難了。看來有必要在學習工作之餘學習學習演算法以及計算機基礎知識了。
翻了上半年參加的程式碼,趁週末整理一下當時的思路以及回顧一下資料結構與演算法。比賽前中期還保持不錯的名次,一直維持在二十名左右以為穩穩三十二強了,結果後期突破不大,最後幾天呼呼的被超過,真是太天真了。後來回想確實方法思路比較死板,一口咬定DFS+剪枝,沒有去嘗試新的演算法如A*,模擬退火演算法等,還有大賽群裡分享說的動態規劃、數模等。
賽題介紹
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;
}