哈哈,我是真的服了,写了好几天结果给我个这,气死我了,果然还有很大的进步空间。如果有c测试点4,就好了。 又写了一天,是真解决不了了,这个问题等我明白一定来解答
哈哈,
测试点 提示 内存(KB) 用时(ms) 结果 得分 0 sample1 多条最短路,同一点有多路,最近点无路,多连通 184 1 答案正确
15 / 15 1 sample 2 聚集型,均离岸远 364 1 答案正确
3 / 3 2 分散型,均跳不到,有在角上 356 1 答案正确
2 / 2 3 有一只在岸上,有一只在岛上,不能算在内 316 2 答案正确
3 / 3 4 最大N,sample1的复杂版,可选路径8条,后面要更新前面的最短路 308 2 答案错误
0 / 6 5 最小N,一步跳到岸 300 2 答案正确
1 / 1
题目大致信息。
This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).
Assume that the lake is a 100 by 100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him a shortest path to reach one of the banks. The length of a path is the number of jumps that James has to make.
Input Specification:
Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of crocodiles, and D, the maximum distance that James could jump. Then N lines follow, each containing the (x,y) location of a crocodile. Note that no two crocodiles are staying at the same position.
Output Specification:
For each test case, if James can escape, output in one line the minimum number of jumps he must make. Then starting from the next line, output the position (x,y) of each crocodile on the path, each pair in one line, from the island to the bank. If it is impossible for James to escape that way, simply give him 0 as the number of jumps. If there are many shortest paths, just output the one with the minimum first jump, which is guaranteed to be unique.
Sample Input 1:
17 15 10 -21 10 21 -40 10 30 -50 20 40 35 10 0 -10 -25 22 40 -40 -30 30 -10 22 0 11 25 21 25 10 10 10 10 35 -30 10
Sample Output 1:
4 0 11 10 21 10 35
Sample Input 2:
4 13 -12 12 12 12 -12 -12 12 -12
Sample Output 2:
0
虽然我不是满分,问题也暂时解决不了,但不妨碍他是一个较好的代码,可以看一下,开头的运行速度,哈哈。毕竟我们相遇必定是为了学习数据结构而来,所以加油。
我的代码主要分为4各部分
首先我先展示头文件,与主函数
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<math.h>int main() {LGraph M;Point *Array;bool *Visited;M = Init_Graph();Array = Read_Point_Array(M ->N);Visited = (bool*)calloc(M ->N + 1, sizeof(bool));M = Build_Graph(M, Array, Visited);if(M){double *dist;int *path;int Node;Stack S;dist = (double*)malloc(sizeof(double) * (M ->N + 1));path = (int*)malloc(sizeof(int) * (M ->N + 1));Dijkstra(M, dist, path);Node = Fllush_Mindata(M, Visited, dist, path);S = Init_Stack();Push_path_data(S, path, Node);Print_Path(S, Array);} return 0; }
第一部分,构造图并插入数据
const double INFITY = 500000.0;typedef struct Coordinate *Point; struct Coordinate{int X;int Y; };typedef struct ENode *PtrToENode; typedef PtrToENode Edge; struct ENode{int V1, V2;double dist; };typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{int V;double dist;PtrToAdjVNode Next; };typedef struct VNode **AdjList; struct VNode{PtrToAdjVNode FirstEdge; };typedef struct GNode *LGraph; struct GNode{int N;double D;AdjList G; };LGraph Build_Graph(LGraph M, Point *Array, bool *Visited); LGraph Init_Graph(); Point* Read_Point_Array(int N); bool Up_ashore(Point P, double D); double Dict_E(Point start, Point end, double D); void Insert_Graph(LGraph M, Edge E);
LGraph Init_Graph() {LGraph M;M = (LGraph)malloc(sizeof(struct GNode));scanf("%d %lf", &M ->N, &M ->D);M ->G = (AdjList)malloc(sizeof(struct VNode) * (M ->N + 1));for(int i = 0; i <= M ->N; i++){M ->G[i] = (struct VNode*)malloc(sizeof(struct VNode));M ->G[i] ->FirstEdge = NULL;}return M; }Point* Read_Point_Array(int N) {Point *Array;Array = (Point*)malloc(sizeof(Point) * (N + 1));Array[0] = (Point)malloc(sizeof(struct Coordinate));Array[0] ->X = 0;Array[0] ->Y = 0;for(int i = 1; i <= N; i++){Array[i] = (Point)malloc(sizeof(struct Coordinate));scanf("%d %d", &(Array[i] ->X), &(Array[i] ->Y));}return Array; }LGraph Build_Graph(LGraph M, Point *Array, bool *Visited) {Edge E;bool Up = false;bool Up_D = false;E = (Edge)malloc(sizeof(struct ENode));if(Up_ashore(Array[0], M ->D + 7.5)){printf("1\n");return NULL;}for(int i = 1; i <= M ->N; i++){if(Up_ashore(Array[i], M ->D + 7.5)){Visited[i] = true;Up = true;}E ->dist = Dict_E(Array[0], Array[i], M ->D + 7.5);E ->V1 = 0;E ->V2 = i;if(E ->dist != 0 && E ->dist > 7.5){Up_D = true;Insert_Graph(M, E);}}if(!Up || !Up_D){printf("0\n");return NULL;}for(int i = 1; i <= M ->N; i++){for(int j = i + 1; j <= M ->N; j++){E ->dist = Dict_E(Array[i], Array[j], M ->D);E ->V1 = i;E ->V2 = j;if(E ->dist != 0){Insert_Graph(M, E);}} }return M; }void Insert_Graph(LGraph M, Edge E) {PtrToAdjVNode NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V2;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V1] ->FirstEdge;M ->G[E ->V1] ->FirstEdge = NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V1;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V2] ->FirstEdge;M ->G[E ->V2] ->FirstEdge = NewNode; } double Dict_E(Point start, Point end, double D) {double dis;dis = sqrt(pow(start ->X - end ->X, 2) + pow(start ->Y - end ->Y, 2));if(dis <= D){return dis;}else{return 0;} } bool Up_ashore(Point P, double D) {return (abs(P ->X) >= 50 - D || abs(P ->Y) >= 50 - D); }
第二部分,构建堆
typedef struct HeapNode *HN; struct HeapNode{int sign;double dist; };typedef struct Heap *MinHeap; struct Heap{HN data;int Size; };MinHeap Init_dist(LGraph M); void Insert_Heap(MinHeap H, double Data, int sign); struct HeapNode Delete_Heap(MinHeap H); void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected);void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected) {PtrToAdjVNode G;for(G = M ->G[head] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V]){Insert_Heap(H, G ->dist, G ->V);}} }void Insert_Graph(LGraph M, Edge E) {PtrToAdjVNode NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V2;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V1] ->FirstEdge;M ->G[E ->V1] ->FirstEdge = NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V1;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V2] ->FirstEdge;M ->G[E ->V2] ->FirstEdge = NewNode; }MinHeap Init_dist(LGraph M) {MinHeap dist;dist = (MinHeap)malloc(sizeof(struct Heap) * (M ->N + 1));dist->data = (HN)malloc(sizeof(struct HeapNode) * (M ->N + 1));dist ->Size = 0;dist ->data[0].sign = -1;dist ->data[0].dist = -1;return dist; } void Insert_Heap(MinHeap H, double Data, int sign) {int i;i = ++(H ->Size);for(; Data < H ->data[i/2].dist; i /= 2){H ->data[i].dist = H ->data[i/2].dist;H ->data[i].sign = H ->data[i/2].sign;}H ->data[i].dist = Data;H ->data[i].sign = sign; } struct HeapNode Delete_Heap(MinHeap H) {int Child, Parent;struct HeapNode Min, Temp;if(H ->Size == 0){return H ->data[0];}Min = H ->data[1];Temp = H ->data[H ->Size --];for(Parent = 1; Parent * 2 <= H ->Size; Parent = Child){Child = Parent * 2;if((Child != H ->Size) && H ->data[Child].dist > H ->data[Child + 1].dist){Child++;}if(Temp.dist <= H ->data[Child].dist){break;}else{H ->data[Parent].dist = H ->data[Child].dist;H ->data[Parent].sign = H ->data[Child].sign;} }H ->data[Parent].dist = Temp.dist;H ->data[Parent].sign = Temp.sign;return Min; }
第三部分,Dijkstra算法,与寻求路径
void Dijkstra(LGraph M, double *dist, int *path) {MinHeap H;struct HeapNode HNode;bool *collected;PtrToAdjVNode G;H = Init_dist(M);collected = (bool*)malloc(sizeof(bool) * (M ->N + 1));Init_DP(dist, path, M ->N);Creat_Heap(0, M, H, collected);dist[0] = 0;collected[0] = true;while(HNode = Delete_Heap(H), HNode.sign != -1){collected[HNode.sign] = true;if(dist[HNode.sign] > HNode.dist){dist[HNode.sign] = HNode.dist;path[HNode.sign] = 0;}for(G = M ->G[HNode.sign] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V] && dist[G ->V] > dist[HNode.sign] + G ->dist){dist[G ->V] = dist[HNode.sign] + G ->dist;path[G ->V] = HNode.sign;Insert_Heap(H, dist[G ->V], G ->V);}} } }void Init_DP(double *dist, int *path, int N) {for(int i = 0; i <= N; i++){dist[i] = INFITY;path[i] = -1;} }
第四部分,求取最小路径,巧用堆栈
typedef struct Node *Stack; struct Node{int data;Stack Next; };bool Find_Root(int *path, int N); int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path); Stack Init_Stack(); void Push_Stack(Stack S, int data); int Pop_Stack(Stack S); bool IsEmpty(Stack S); void Push_path_data(Stack S, int *path, int Node); void Print_Path(Stack S, Point *Array);void Print_Path(Stack S, Point *Array) {int Node;printf("%d\n", S ->data);while(!IsEmpty(S)){Node = Pop_Stack(S);printf("%d %d\n", Array[Node] ->X, Array[Node] ->Y);} } void Push_path_data(Stack S, int *path, int Node) {if(Node == 0){return ;}if(Node != 0){Push_Stack(S, Node);S ->data++;}Push_path_data(S, path, path[Node]); } int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path) {int N, Node;int Cycle;int MinCycle = (int)INFITY;double dmin = INFITY;double MinJump;int MinSkip;for(int i = 1; i <= M ->N; i++){Cycle = 0;if(Visited[i] && Find_Root(path, i)){N = i;while(N != 0){if(path[N] == 0){MinSkip = N;}N = path[N];Cycle++;}if(Cycle == MinCycle){if(dist[i] < dmin){Node = i;}if(dist[i] == dmin){if(dist[MinSkip] < MinJump){Node = i;}}}if(Cycle < MinCycle){dmin = dist[i];MinJump = dist[MinSkip];MinCycle = Cycle;Node = i; }}}return Node; } bool Find_Root(int *path, int N) {if(N == 0){return true;}if(N == -1){return false;}return Find_Root(path, path[N]); }Stack Init_Stack() {Stack S;S = (Stack)malloc(sizeof(struct Node));S ->data = 1;S ->Next = NULL;return S; } void Push_Stack(Stack S, int data) {Stack T;T = (Stack)malloc(sizeof(struct Node));T ->data = data;T ->Next = S ->Next;S ->Next = T; } int Pop_Stack(Stack S) {int temp;Stack Top;if(IsEmpty(S)){printf("IS Empty the Stack!\n");return -1;}else{Top = S ->Next;S ->Next = Top ->Next;temp = Top ->data;free(Top);return temp;} } bool IsEmpty(Stack S) {return (S->Next == NULL); }
我的全部AC:
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<math.h>const double INFITY = 500000.0;typedef struct Coordinate *Point; struct Coordinate{int X;int Y; };typedef struct ENode *PtrToENode; typedef PtrToENode Edge; struct ENode{int V1, V2;double dist; };typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{int V;double dist;PtrToAdjVNode Next; };typedef struct VNode **AdjList; struct VNode{PtrToAdjVNode FirstEdge; };typedef struct GNode *LGraph; struct GNode{int N;double D;AdjList G; };typedef struct HeapNode *HN; struct HeapNode{int sign;double dist; };typedef struct Heap *MinHeap; struct Heap{HN data;int Size; };typedef struct Node *Stack; struct Node{int data;Stack Next; };LGraph Build_Graph(LGraph M, Point *Array, bool *Visited); LGraph Init_Graph(); Point* Read_Point_Array(int N); bool Up_ashore(Point P, double D); double Dict_E(Point start, Point end, double D); void Insert_Graph(LGraph M, Edge E); MinHeap Init_dist(LGraph M); void Insert_Heap(MinHeap H, double Data, int sign); struct HeapNode Delete_Heap(MinHeap H); void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected); void Init_DP(double *dist, int *path, int N); void Dijkstra(LGraph M, double *dist, int *path); bool Find_Root(int *path, int N); int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path); Stack Init_Stack(); void Push_Stack(Stack S, int data); int Pop_Stack(Stack S); bool IsEmpty(Stack S); void Push_path_data(Stack S, int *path, int Node); void Print_Path(Stack S, Point *Array);int main() {LGraph M;Point *Array;bool *Visited;M = Init_Graph();Array = Read_Point_Array(M ->N);Visited = (bool*)calloc(M ->N + 1, sizeof(bool));M = Build_Graph(M, Array, Visited);if(M){double *dist;int *path;int Node;Stack S;dist = (double*)malloc(sizeof(double) * (M ->N + 1));path = (int*)malloc(sizeof(int) * (M ->N + 1));Dijkstra(M, dist, path);Node = Fllush_Mindata(M, Visited, dist, path);S = Init_Stack();Push_path_data(S, path, Node);Print_Path(S, Array);} return 0; } void Print_Path(Stack S, Point *Array) {int Node;printf("%d\n", S ->data);while(!IsEmpty(S)){Node = Pop_Stack(S);printf("%d %d\n", Array[Node] ->X, Array[Node] ->Y);} } void Push_path_data(Stack S, int *path, int Node) {if(Node == 0){return ;}if(Node != 0){Push_Stack(S, Node);S ->data++;}Push_path_data(S, path, path[Node]); } int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path) {int N, Node;int Cycle;int MinCycle = (int)INFITY;double dmin = INFITY;double MinJump;int MinSkip;for(int i = 1; i <= M ->N; i++){Cycle = 0;if(Visited[i] && Find_Root(path, i)){N = i;while(N != 0){if(path[N] == 0){MinSkip = N;}N = path[N];Cycle++;}if(Cycle == MinCycle){if(dist[i] < dmin){Node = i;}if(dist[i] == dmin){if(dist[MinSkip] < MinJump){Node = i;}}}if(Cycle < MinCycle){dmin = dist[i];MinJump = dist[MinSkip];MinCycle = Cycle;Node = i; }}}return Node; } bool Find_Root(int *path, int N) {if(N == 0){return true;}if(N == -1){return false;}return Find_Root(path, path[N]); } LGraph Build_Graph(LGraph M, Point *Array, bool *Visited) {Edge E;bool Up = false;bool Up_D = false;E = (Edge)malloc(sizeof(struct ENode));if(Up_ashore(Array[0], M ->D + 7.5)){printf("1\n");return NULL;}for(int i = 1; i <= M ->N; i++){if(Up_ashore(Array[i], M ->D + 7.5)){Visited[i] = true;Up = true;}E ->dist = Dict_E(Array[0], Array[i], M ->D + 7.5);E ->V1 = 0;E ->V2 = i;if(E ->dist != 0 && E ->dist > 7.5){Up_D = true;Insert_Graph(M, E);}}if(!Up || !Up_D){printf("0\n");return NULL;}for(int i = 1; i <= M ->N; i++){for(int j = i + 1; j <= M ->N; j++){E ->dist = Dict_E(Array[i], Array[j], M ->D);E ->V1 = i;E ->V2 = j;if(E ->dist != 0){Insert_Graph(M, E);}} }return M; } void Dijkstra(LGraph M, double *dist, int *path) {MinHeap H;struct HeapNode HNode;bool *collected;PtrToAdjVNode G;H = Init_dist(M);collected = (bool*)malloc(sizeof(bool) * (M ->N + 1));Init_DP(dist, path, M ->N);Creat_Heap(0, M, H, collected);dist[0] = 0;collected[0] = true;while(HNode = Delete_Heap(H), HNode.sign != -1){collected[HNode.sign] = true;if(dist[HNode.sign] > HNode.dist){dist[HNode.sign] = HNode.dist;path[HNode.sign] = 0;}for(G = M ->G[HNode.sign] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V] && dist[G ->V] > dist[HNode.sign] + G ->dist){dist[G ->V] = dist[HNode.sign] + G ->dist;path[G ->V] = HNode.sign;Insert_Heap(H, dist[G ->V], G ->V);}} } }void Init_DP(double *dist, int *path, int N) {for(int i = 0; i <= N; i++){dist[i] = INFITY;path[i] = -1;} } void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected) {PtrToAdjVNode G;for(G = M ->G[head] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V]){Insert_Heap(H, G ->dist, G ->V);}} }void Insert_Graph(LGraph M, Edge E) {PtrToAdjVNode NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V2;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V1] ->FirstEdge;M ->G[E ->V1] ->FirstEdge = NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V1;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V2] ->FirstEdge;M ->G[E ->V2] ->FirstEdge = NewNode; }LGraph Init_Graph() {LGraph M;M = (LGraph)malloc(sizeof(struct GNode));scanf("%d %lf", &M ->N, &M ->D);M ->G = (AdjList)malloc(sizeof(struct VNode) * (M ->N + 1));for(int i = 0; i <= M ->N; i++){M ->G[i] = (struct VNode*)malloc(sizeof(struct VNode));M ->G[i] ->FirstEdge = NULL;}return M; }Point* Read_Point_Array(int N) {Point *Array;Array = (Point*)malloc(sizeof(Point) * (N + 1));Array[0] = (Point)malloc(sizeof(struct Coordinate));Array[0] ->X = 0;Array[0] ->Y = 0;for(int i = 1; i <= N; i++){Array[i] = (Point)malloc(sizeof(struct Coordinate));scanf("%d %d", &(Array[i] ->X), &(Array[i] ->Y));}return Array; } double Dict_E(Point start, Point end, double D) {double dis;dis = sqrt(pow(start ->X - end ->X, 2) + pow(start ->Y - end ->Y, 2));if(dis <= D){return dis;}else{return 0;} } bool Up_ashore(Point P, double D) {return (abs(P ->X) >= 50 - D || abs(P ->Y) >= 50 - D); }MinHeap Init_dist(LGraph M) {MinHeap dist;dist = (MinHeap)malloc(sizeof(struct Heap) * (M ->N + 1));dist->data = (HN)malloc(sizeof(struct HeapNode) * (M ->N + 1));dist ->Size = 0;dist ->data[0].sign = -1;dist ->data[0].dist = -1;return dist; } void Insert_Heap(MinHeap H, double Data, int sign) {int i;i = ++(H ->Size);for(; Data < H ->data[i/2].dist; i /= 2){H ->data[i].dist = H ->data[i/2].dist;H ->data[i].sign = H ->data[i/2].sign;}H ->data[i].dist = Data;H ->data[i].sign = sign; } struct HeapNode Delete_Heap(MinHeap H) {int Child, Parent;struct HeapNode Min, Temp;if(H ->Size == 0){return H ->data[0];}Min = H ->data[1];Temp = H ->data[H ->Size --];for(Parent = 1; Parent * 2 <= H ->Size; Parent = Child){Child = Parent * 2;if((Child != H ->Size) && H ->data[Child].dist > H ->data[Child + 1].dist){Child++;}if(Temp.dist <= H ->data[Child].dist){break;}else{H ->data[Parent].dist = H ->data[Child].dist;H ->data[Parent].sign = H ->data[Child].sign;} }H ->data[Parent].dist = Temp.dist;H ->data[Parent].sign = Temp.sign;return Min; }Stack Init_Stack() {Stack S;S = (Stack)malloc(sizeof(struct Node));S ->data = 1;S ->Next = NULL;return S; } void Push_Stack(Stack S, int data) {Stack T;T = (Stack)malloc(sizeof(struct Node));T ->data = data;T ->Next = S ->Next;S ->Next = T; } int Pop_Stack(Stack S) {int temp;Stack Top;if(IsEmpty(S)){printf("IS Empty the Stack!\n");return -1;}else{Top = S ->Next;S ->Next = Top ->Next;temp = Top ->data;free(Top);return temp;} } bool IsEmpty(Stack S) {return (S->Next == NULL); }
下面是我的测试代码,后期我会在刷新数据,参考我上述的全部代码。
主要是,之前为了解决问题搞得测试代码,现在是真服了,我解决
有朋友问,后面的跟新前面的最短路径,这是我的测试更新,以及具体点位。
dist[1] : dist[7] + E(1 -> 7) 500000.000000 : 10.000000 + 14.866069更新完成! dist[1] : dist[7] + E(1 -> 7) 24.866069 : 10.000000 + 14.866069dist[15] : dist[12] + E(15 -> 12) 500000.000000 : 11.000000 + 10.049876更新完成! dist[15] : dist[12] + E(15 -> 12) 21.049876 : 11.000000 + 10.049876dist[11] : dist[12] + E(11 -> 12) 500000.000000 : 11.000000 + 14.866069更新完成! dist[11] : dist[12] + E(11 -> 12) 25.866069 : 11.000000 + 14.866069dist[2] : dist[12] + E(2 -> 12) 500000.000000 : 11.000000 + 14.142136更新完成! dist[2] : dist[12] + E(2 -> 12) 25.142136 : 11.000000 + 14.142136dist[14] : dist[15] + E(14 -> 15) 500000.000000 : 14.142136 + 15.000000更新完成! dist[14] : dist[15] + E(14 -> 15) 29.142136 : 14.142136 + 15.000000dist[2] : dist[15] + E(2 -> 15) 25.142136 : 14.142136 + 11.000000dist[14] : dist[15] + E(14 -> 15) 29.142136 : 14.142136 + 15.000000dist[2] : dist[15] + E(2 -> 15) 25.142136 : 14.142136 + 11.000000dist[16] : dist[2] + E(16 -> 2) 500000.000000 : 25.142136 + 14.000000更新完成! dist[16] : dist[2] + E(16 -> 2) 39.142136 : 25.142136 + 14.000000dist[13] : dist[2] + E(13 -> 2) 500000.000000 : 25.142136 + 15.000000更新完成! dist[13] : dist[2] + E(13 -> 2) 40.142136 : 25.142136 + 15.000000dist[8] : dist[11] + E(8 -> 11) 500000.000000 : 25.866069 + 15.000000更新完成! dist[8] : dist[11] + E(8 -> 11) 40.866069 : 25.866069 + 15.000000dist[13] : dist[14] + E(13 -> 14) 40.142136 : 29.142136 + 11.000000dist[6] : dist[14] + E(6 -> 14) 500000.000000 : 29.142136 + 10.000000更新完成! dist[6] : dist[14] + E(6 -> 14) 39.142136 : 29.142136 + 10.000000dist[5] : dist[16] + E(5 -> 16) 500000.000000 : 39.142136 + 11.180340更新完成! dist[5] : dist[16] + E(5 -> 16) 50.322476 : 39.142136 + 11.180340dist[13] : dist[6] + E(13 -> 6) 40.142136 : 39.142136 + 14.866069dist[17] : dist[8] + E(17 -> 8) 500000.000000 : 40.866069 + 13.000000更新完成! dist[17] : dist[8] + E(17 -> 8) 53.866069 : 40.866069 + 13.000000dist[10] : dist[8] + E(10 -> 8) 500000.000000 : 40.866069 + 9.433981更新完成! dist[10] : dist[8] + E(10 -> 8) 50.300050 : 40.866069 + 9.433981dist[3] : dist[17] + E(3 -> 17) 500000.000000 : 53.866069 + 10.000000更新完成! dist[3] : dist[17] + E(3 -> 17) 63.866069 : 53.866069 + 10.000000 Visited[0] = 0 dist[0] = 0.000000 path[0] = -1 Visited[1] = 0 dist[1] = 24.866069 path[1] = 7 Visited[2] = 0 dist[2] = 25.142136 path[2] = 12 Visited[3] = 1 dist[3] = 63.866069 path[3] = 17 Visited[4] = 1 dist[4] = 500000.000000 path[4] = -1 Visited[5] = 1 dist[5] = 50.322476 path[5] = 16 Visited[6] = 1 dist[6] = 39.142136 path[6] = 14 Visited[7] = 0 dist[7] = 10.000000 path[7] = 0 Visited[8] = 0 dist[8] = 40.866069 path[8] = 11 Visited[9] = 1 dist[9] = 500000.000000 path[9] = -1 Visited[10] = 1 dist[10] = 50.300050 path[10] = 8 Visited[11] = 0 dist[11] = 25.866069 path[11] = 12 Visited[12] = 0 dist[12] = 11.000000 path[12] = 0 Visited[13] = 0 dist[13] = 40.142136 path[13] = 2 Visited[14] = 0 dist[14] = 29.142136 path[14] = 15 Visited[15] = 0 dist[15] = 14.142136 path[15] = 0 Visited[16] = 1 dist[16] = 39.142136 path[16] = 2 Visited[17] = 1 dist[17] = 53.866069 path[17] = 8
2024,10.26更新了一下,发现我的Dijkstra算法用错了,这是以前的,哈哈,我这样就无法保持根了,但是我发现依旧无妨解决问题时,更加难受了。
void Dijkstra(LGraph M, double *dist, int *path) {MinHeap H;struct HeapNode HNode;bool *collected;PtrToAdjVNode G;H = Init_dist(M);collected = (bool*)malloc(sizeof(bool) * (M ->N + 1));Init_DP(dist, path, M ->N);for(int i = 0; i <= M ->N; i++){Creat_Heap(i, M, H, collected);collected[i] = true;while(HNode = Delete_Heap(H), HNode.sign != -1){collected[HNode.sign] = true;if(dist[HNode.sign] > HNode.dist){dist[HNode.sign] = HNode.dist;path[HNode.sign] = i;}for(G = M ->G[HNode.sign] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V] && dist[G ->V] > dist[HNode.sign] + G ->dist){dist[G ->V] = dist[HNode.sign] + G ->dist;path[G ->V] = HNode.sign;}}} } }
如我在这里的判定,感觉够可以了吧,先考虑最小跳跃,其次最短距离,最后最小跳。tmd我是真服了!
int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path) {int N, Node;int Cycle;int MinCycle = (int)INFITY;double dmin = INFITY;double MinJump;int MinSkip;for(int i = 1; i <= M ->N; i++){Cycle = 0;if(Visited[i] && Find_Root(path, i)){N = i;while(N != 0){if(path[N] == 0){MinSkip = N;}N = path[N];Cycle++;}if(Cycle == MinCycle){if(dist[i] < dmin){Node = i;}if(dist[i] == dmin){if(dist[MinSkip] < MinJump){Node = i;}}}if(Cycle < MinCycle){dmin = dist[i];MinJump = dist[MinSkip];MinCycle = Cycle;Node = i; }}}return Node; }
之前的错误代码留个纪念
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<math.h>const double INFITY = 500000.0;typedef struct Coordinate *Point; struct Coordinate{int X;int Y; };typedef struct ENode *PtrToENode; typedef PtrToENode Edge; struct ENode{int V1, V2;double dist; };typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{int V;double dist;PtrToAdjVNode Next; };typedef struct VNode **AdjList; struct VNode{PtrToAdjVNode FirstEdge; };typedef struct GNode *LGraph; struct GNode{int N;double D;AdjList G; };typedef struct HeapNode *HN; struct HeapNode{int sign;double dist; };typedef struct Heap *MinHeap; struct Heap{HN data;int Size; };typedef struct Node *Stack; struct Node{int data;Stack Next; };LGraph Build_Graph(LGraph M, Point *Array, bool *Visited); LGraph Init_Graph(); Point* Read_Point_Array(int N); bool Up_ashore(Point P, double D); double Dict_E(Point start, Point end, double D); void Insert_Graph(LGraph M, Edge E); MinHeap Init_dist(LGraph M); void Insert_Heap(MinHeap H, double Data, int sign); struct HeapNode Delete_Heap(MinHeap H); void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected); void Init_DP(double *dist, int *path, int N); void Dijkstra(LGraph M, double *dist, int *path); bool Find_Root(int *path, int N); int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path); Stack Init_Stack(); void Push_Stack(Stack S, int data); int Pop_Stack(Stack S); bool IsEmpty(Stack S); void Push_path_data(Stack S, int *path, int Node); void Print_Path(Stack S, Point *Array);int main() {LGraph M;Point *Array;bool *Visited;M = Init_Graph();Array = Read_Point_Array(M ->N);Visited = (bool*)calloc(M ->N + 1, sizeof(bool));M = Build_Graph(M, Array, Visited);if(M){double *dist;int *path;int Node;Stack S;dist = (double*)malloc(sizeof(double) * (M ->N + 1));path = (int*)malloc(sizeof(int) * (M ->N + 1));Dijkstra(M, dist, path);Node = Fllush_Mindata(M, Visited, dist, path);S = Init_Stack();Push_path_data(S, path, Node);Print_Path(S, Array);} return 0; } void Print_Path(Stack S, Point *Array) {int Node;printf("%d\n", S ->data);while(!IsEmpty(S)){Node = Pop_Stack(S);printf("%d %d\n", Array[Node] ->X, Array[Node] ->Y);} } void Push_path_data(Stack S, int *path, int Node) {if(Node == 0){return ;}if(Node != 0){Push_Stack(S, Node);S ->data++;}Push_path_data(S, path, path[Node]); } int Fllush_Mindata(LGraph M, bool *Visited, double *dist, int *path) {int N, Node;int Cycle;int MinCycle = (int)INFITY;double dmin = INFITY;for(int i = 1; i <= M ->N; i++){Cycle = 0;if(Visited[i] && Find_Root(path, i)){N = path[i];while(N != 0){dist[i] += dist[N];N = path[N];Cycle++;}if(Cycle == MinCycle){if(dist[i] < dmin){Node = i;}}if(Cycle < MinCycle){dmin = dist[i];MinCycle = Cycle;Node = i; }}}return Node; } bool Find_Root(int *path, int N) {if(N == 0){return true;}if(N == -1){return false;}return Find_Root(path, path[N]); } LGraph Build_Graph(LGraph M, Point *Array, bool *Visited) {Edge E;bool Up = false;bool Up_D = false;E = (Edge)malloc(sizeof(struct ENode));if(Up_ashore(Array[0], M ->D + 7.5)){printf("1\n");return NULL;}for(int i = 1; i <= M ->N; i++){if(Up_ashore(Array[i], M ->D + 7.5)){Visited[i] = true;Up = true;}E ->dist = Dict_E(Array[0], Array[i], M ->D + 7.5);E ->V1 = 0;E ->V2 = i;if(E ->dist != 0 && E ->dist > 7.5){Up_D = true;Insert_Graph(M, E);}}if(!Up || !Up_D){printf("0\n");return NULL;}for(int i = 1; i <= M ->N; i++){for(int j = i + 1; j <= M ->N; j++){E ->dist = Dict_E(Array[i], Array[j], M ->D);E ->V1 = i;E ->V2 = j;if(E ->dist != 0){Insert_Graph(M, E);}} }return M; } void Dijkstra(LGraph M, double *dist, int *path) {MinHeap H;struct HeapNode HNode;bool *collected;PtrToAdjVNode G;H = Init_dist(M);collected = (bool*)malloc(sizeof(bool) * (M ->N + 1));Init_DP(dist, path, M ->N);for(int i = 0; i <= M ->N; i++){Creat_Heap(i, M, H, collected);collected[i] = true;while(HNode = Delete_Heap(H), HNode.sign != -1){collected[HNode.sign] = true;if(dist[HNode.sign] > HNode.dist){dist[HNode.sign] = HNode.dist;path[HNode.sign] = i;}for(G = M ->G[HNode.sign] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V] && dist[G ->V] > dist[HNode.sign] + G ->dist){dist[G ->V] = dist[HNode.sign] + G ->dist;path[G ->V] = HNode.sign;}}} } }void Init_DP(double *dist, int *path, int N) {for(int i = 0; i <= N; i++){dist[i] = INFITY;path[i] = -1;} } void Creat_Heap(int head, LGraph M, MinHeap H, bool *collected) {PtrToAdjVNode G;for(G = M ->G[head] ->FirstEdge; G; G = G ->Next){if(!collected[G ->V]){Insert_Heap(H, G ->dist, G ->V);}} }void Insert_Graph(LGraph M, Edge E) {PtrToAdjVNode NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V2;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V1] ->FirstEdge;M ->G[E ->V1] ->FirstEdge = NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode ->V = E ->V1;NewNode ->dist = E ->dist;NewNode ->Next = M ->G[E ->V2] ->FirstEdge;M ->G[E ->V2] ->FirstEdge = NewNode; }LGraph Init_Graph() {LGraph M;M = (LGraph)malloc(sizeof(struct GNode));scanf("%d %lf", &M ->N, &M ->D);M ->G = (AdjList)malloc(sizeof(struct VNode) * (M ->N + 1));for(int i = 0; i <= M ->N; i++){M ->G[i] = (struct VNode*)malloc(sizeof(struct VNode));M ->G[i] ->FirstEdge = NULL;}return M; } Point* Read_Point_Array(int N) {Point *Array;Array = (Point*)malloc(sizeof(Point) * (N + 1));Array[0] = (Point)malloc(sizeof(struct Coordinate));Array[0] ->X = 0;Array[0] ->Y = 0;for(int i = 1; i <= N; i++){Array[i] = (Point)malloc(sizeof(struct Coordinate));scanf("%d %d", &(Array[i] ->X), &(Array[i] ->Y));}return Array; } double Dict_E(Point start, Point end, double D) {double dis;dis = sqrt(pow(start ->X - end ->X, 2) + pow(start ->Y - end ->Y, 2));if(dis <= D){return dis;}else{return 0;} } bool Up_ashore(Point P, double D) {return (abs(P ->X) >= 50 - D || abs(P ->Y) >= 50 - D); }MinHeap Init_dist(LGraph M) {MinHeap dist;dist = (MinHeap)malloc(sizeof(struct Heap) * (M ->N + 1));dist->data = (HN)malloc(sizeof(struct HeapNode) * (M ->N + 1));dist ->Size = 0;dist ->data[0].sign = -1;dist ->data[0].dist = -1;return dist; } void Insert_Heap(MinHeap H, double Data, int sign) {int i;i = ++(H ->Size);for(; Data < H ->data[i/2].dist; i /= 2){H ->data[i].dist = H ->data[i/2].dist;H ->data[i].sign = H ->data[i/2].sign;}H ->data[i].dist = Data;H ->data[i].sign = sign; } struct HeapNode Delete_Heap(MinHeap H) {int Child, Parent;struct HeapNode Min, Temp;if(H ->Size == 0){return H ->data[0];}Min = H ->data[1];Temp = H ->data[H ->Size --];for(Parent = 1; Parent * 2 <= H ->Size; Parent = Child){Child = Parent * 2;if((Child != H ->Size) && H ->data[Child].dist > H ->data[Child + 1].dist){Child++;}if(Temp.dist <= H ->data[Child].dist){break;}else{H ->data[Parent].dist = H ->data[Child].dist;H ->data[Parent].sign = H ->data[Child].sign;} }H ->data[Parent].dist = Temp.dist;H ->data[Parent].sign = Temp.sign;return Min; }Stack Init_Stack() {Stack S;S = (Stack)malloc(sizeof(struct Node));S ->data = 1;S ->Next = NULL;return S; } void Push_Stack(Stack S, int data) {Stack T;T = (Stack)malloc(sizeof(struct Node));T ->data = data;T ->Next = S ->Next;S ->Next = T; } int Pop_Stack(Stack S) {int temp;Stack Top;if(IsEmpty(S)){printf("IS Empty the Stack!\n");return -1;}else{Top = S ->Next;S ->Next = Top ->Next;temp = Top ->data;free(Top);return temp;} } bool IsEmpty(Stack S) {return (S->Next == NULL); }