大致思路:
將地鐵線路的抽象問題轉化為圖上最短路徑的具體問題,那么最大的難點如何抽象出來。
1.用結構體存儲每個站點的信息:包括編號、名稱、所經過的線路;
2.names數組存儲每個不通過站點的名字,其下表對應着站點的標號,這樣讀取數據時,可以利用它保證每個站點不被重復構建;
3.map二維數組存儲每個站點間的距離;
基本靠以上數據結構就可以將問題具體化了,然后就轉為圖上的路徑規划問題,利用dfs等算法即可解決。
效果展示(推薦dev進行代碼運行):
代碼:
純C版本:
#include <stdio.h> #include <string.h> // 站點信息 typedef struct Station{ char name[30]; // 站點名稱 int lines[20]; // 經過的線路 int cnt; // 線路數量 }Station; Station stations[100]; // 站點間收費 double map[100][100]; // 站點數量 int staNum; // 站點名稱 char names[100][30]; // 標記是否訪問過 int visit[100]; // 可選路線數量: int ansNum; // 最優路線: int minLu[100]; // 最優路線中站數量: int minCnt; // 最優價格: double minPrict; // 當前線路: int nowLu[100]; // 查找路線: void dfs(int id1, int id2, int ct, double cost){ int i, j; if(id1 == id2){ printf("可選路線%d:\n", ++ansNum); for(i = 0; i < ct; i++){ if(i == 0) printf("%s", names[nowLu[i]]); else printf(" -> %s", names[nowLu[i]]); printf("("); for(j = 0; j < stations[nowLu[i]].cnt; j++){ printf("%d,", stations[nowLu[i]].lines[j]); } printf(")"); } printf(" [費用:%lf]\n", cost); // 是否最優: if(cost < minPrict){ minCnt = ct; minPrict = cost; for(i = 0; i < ct; i++){ minLu[i] = nowLu[i]; } } } for(i = 0; i < staNum; i++){ // printf("%d %d %lf %d\n ", id1, id2, map[id1][i], 0x3f3f3f3f, visit[i]); if(i != id1 && map[id1][i] < 0x3f3f3f3f && visit[i] == 0){ visit[i] = 1; nowLu[ct] = i; // printf("%d %d %d %d %d ",id1, id2, i, ct, nowLu[ct]); dfs(i, id2, ct + 1, cost + map[id1][i]); visit[i] = 0; } } } int main() { // 讀入文件:包含線路信息 FILE *fp; int i, j; int id2; fp = fopen("data.txt","r"); //需要創建a.txt文件,然后寫入兩個數據,空格隔開 // memset(map, 0x3f3f3f3f, sizeof(map)); for (i = 0; i < 100; i++){ for(j = 0; j < 100; j++){ map[i][j] = 0x3f3f3f3f; } } // 站點數量 staNum = 0; for(i = 1; i <= 5; i++){ printf("[%d號線] ", i); while(1){ double f=0; char name1[30]; char name2[30]; fscanf( fp, "%s", &name1); // 每條線路結束符規定為# if(name1[0] == '#'){ printf("\n", i); break; } // 查找當前站點是否存在 int id1 = -1; for(j = 0; j < staNum; j++){ if(strcmp(name1, names[j]) == 0){ id1 = j; break; } } // 如果當前站點不存在,則需要創建 if(id1 == -1){ id1 = staNum; strcpy(names[id1], name1); // stations[id1].name = name1; // 存入名字 strcpy(stations[id1].name, name1); stations[id1].lines[0] = i; // 存入線路 stations[id1].cnt = 1; // 所經過的線路 staNum++; } else{ if (stations[id1].lines[stations[id1].cnt-1] != i){ //考慮是否需要把當前所在線路標號(即線路幾)存入該站點的lines stations[id1].lines[stations[id1].cnt] = i; // printf("||| i = %d, %s", i, name1); stations[id1].cnt++; } } // 讀入數據: fscanf( fp, "%s%lf", &name2, &f); // 查找當前站點是否存在 id2 = -1; for(j = 0; j < staNum; j++){ if(strcmp(name2, names[j]) == 0){ id2 = j; break; } } // 如果當前站點不存在,則需要創建 if(id2 == -1){ id2 = staNum; // names[id2] = name2; strcpy(names[id2], name2); // stations[id2].name = name2; // 存入名字 strcpy(stations[id2].name, name2); stations[id2].lines[0] = i; // 存入線路 stations[id2].cnt = 1; // 所經過的線路 staNum++; } else{ if(stations[id2].lines[stations[id2].cnt-1] != i){ stations[id2].lines[stations[id2].cnt] = i; // printf("[ i = %d, %d %s] ", i, stations[id2].cnt, name2); stations[id2].cnt++; } } // 加入權重: map[id1][id2] = map[id2][id1] = f; printf("%s->%s %lf ", name1, name2, f); } printf("\n"); } // for(int i = 0; i < staNum; i++){ // printf("%s ", stations[i].name); // for(int j = 0; j < stations[i].cnt; j++){ // printf("%d,", stations[i].lines[j]); // } // printf("\n"); // } // printf("\n"); // 打印矩陣: // for (int i = 0; i < staNum; i++){ // for(int j = 0; j < staNum; j++){ // printf("%lf ", map[i][j]); // } // printf("\n"); // } fclose(fp); // 功能啟動: while(1){ // 輸入需要查找的線路: char n1[30]; char n2[30]; int i, j; // 查找當前站點是否存在 int id1 = -1, id2 = -1; printf("請輸入起始點和終點:\n"); scanf("%s %s", n1, n2); for(j = 0; j < staNum; j++){ if(strcmp(n1, names[j]) == 0){ id1 = j; } // else{ // printf("%s %s\n", n1, names[j]); // } if(strcmp(n2, names[j]) == 0){ id2 = j; } } // printf("id1 %s id2 %s\n", n1, n2); // printf("您查找的起始點和終點分別是: %s -> %s\n", n1, n2); if(id1 == -1 || id2 == -1){ printf("您輸入的名稱不存在!\n"); continue; } printf("您查找的起始點和終點分別是: %s -> %s\n", n1, n2); // 清空數組 memset(visit, 0, sizeof(visit)); // 可選路線數量 ansNum = 0; nowLu[0] = id1; // 放入起點 visit[id1] = 1; minPrict = 0x3f3f3f3f; // 初始化最優價格 dfs(id1, id2, 1, 0); // 起點, 終點, 路線中數據點個數, 價格 for(i = 0; i < minCnt; i++){ if(i == 0) printf("最優路線:%s", names[minLu[i]]); else printf(" -> %s", names[minLu[i]]); printf("("); for(j = 0; j < stations[minLu[i]].cnt; j++){ printf("%d,", stations[minLu[i]].lines[j]); } printf(")"); } printf(" [費用:%lf]\n", minPrict); printf("本次查找結束!!!\n\n"); } return 0; }
C++版:
#include <stdio.h> #include <string.h> // 站點信息 typedef struct Station{ char name[30]; // 站點名稱 int lines[20]; // 經過的線路 int cnt; // 線路數量 }Station; Station stations[100]; // 站點間收費 double map[100][100]; // 站點數量 int staNum; // 站點名稱 char names[100][30]; // 標記是否訪問過 int visit[100]; // 可選路線數量: int ansNum; // 最優路線: int minLu[100]; // 最優路線中站數量: int minCnt; // 最優價格: double minPrict; // 當前線路: int nowLu[100]; // 查找路線: void dfs(int id1, int id2, int ct, double cost){ if(id1 == id2){ printf("可選路線%d:\n", ++ansNum); for(int i = 0; i < ct; i++){ if(i == 0) printf("%s", names[nowLu[i]]); else printf(" -> %s", names[nowLu[i]]); printf("("); for(int j = 0; j < stations[nowLu[i]].cnt; j++){ printf("%d,", stations[nowLu[i]].lines[j]); } printf(")"); } printf(" [費用:%lf]\n", cost); // 是否最優: if(cost < minPrict){ minCnt = ct; minPrict = cost; for(int i = 0; i < ct; i++){ minLu[i] = nowLu[i]; } } } for(int i = 0; i < staNum; i++){ // printf("%d %d %lf %d\n ", id1, id2, map[id1][i], 0x3f3f3f3f, visit[i]); if(i != id1 && map[id1][i] < 0x3f3f3f3f && visit[i] == 0){ visit[i] = 1; nowLu[ct] = i; // printf("%d %d %d %d %d ",id1, id2, i, ct, nowLu[ct]); dfs(i, id2, ct + 1, cost + map[id1][i]); visit[i] = 0; } } } int main() { // 讀入文件:包含線路信息 FILE *fp; fp = fopen("data.txt","r"); //需要創建a.txt文件,然后寫入兩個數據,空格隔開 // memset(map, 0x3f3f3f3f, sizeof(map)); for (int i = 0; i < 100; i++){ for(int j = 0; j < 100; j++){ map[i][j] = 0x3f3f3f3f; } } // 站點數量 staNum = 0; for(int i = 1; i <= 5; i++){ printf("[%d號線] ", i); while(1){ double f=0; char name1[30]; char name2[30]; fscanf( fp, "%s", &name1); // 每條線路結束符規定為# if(name1[0] == '#'){ printf("\n", i); break; } // 查找當前站點是否存在 int id1 = -1; for(int j = 0; j < staNum; j++){ if(strcmp(name1, names[j]) == 0){ id1 = j; break; } } // 如果當前站點不存在,則需要創建 if(id1 == -1){ id1 = staNum; strcpy(names[id1], name1); // stations[id1].name = name1; // 存入名字 strcpy(stations[id1].name, name1); stations[id1].lines[0] = i; // 存入線路 stations[id1].cnt = 1; // 所經過的線路 staNum++; } else{ if (stations[id1].lines[stations[id1].cnt-1] != i){ stations[id1].lines[stations[id1].cnt] = i; // printf("||| i = %d, %s", i, name1); stations[id1].cnt++; } } // 讀入數據: fscanf( fp, "%s%lf", &name2, &f); // 查找當前站點是否存在 int id2 = -1; for(int j = 0; j < staNum; j++){ if(strcmp(name2, names[j]) == 0){ id2 = j; break; } } // 如果當前站點不存在,則需要創建 if(id2 == -1){ id2 = staNum; // names[id2] = name2; strcpy(names[id2], name2); // stations[id2].name = name2; // 存入名字 strcpy(stations[id2].name, name2); stations[id2].lines[0] = i; // 存入線路 stations[id2].cnt = 1; // 所經過的線路 staNum++; } else{ if(stations[id2].lines[stations[id2].cnt-1] != i){ stations[id2].lines[stations[id2].cnt] = i; // printf("[ i = %d, %d %s] ", i, stations[id2].cnt, name2); stations[id2].cnt++; } } // 加入權重: map[id1][id2] = map[id2][id1] = f; printf("%s->%s %lf ", name1, name2, f); } printf("\n"); } // for(int i = 0; i < staNum; i++){ // printf("%s ", stations[i].name); // for(int j = 0; j < stations[i].cnt; j++){ // printf("%d,", stations[i].lines[j]); // } // printf("\n"); // } // printf("\n"); // 打印矩陣: // for (int i = 0; i < staNum; i++){ // for(int j = 0; j < staNum; j++){ // printf("%lf ", map[i][j]); // } // printf("\n"); // } fclose(fp); // 功能啟動: while(1){ // 輸入需要查找的線路: char n1[30]; char n2[30]; printf("請輸入起始點和終點:\n"); scanf("%s %s", n1, n2); // 查找當前站點是否存在 int id1 = -1, id2 = -1; for(int j = 0; j < staNum; j++){ if(strcmp(n1, names[j]) == 0){ id1 = j; } // else{ // printf("%s %s\n", n1, names[j]); // } if(strcmp(n2, names[j]) == 0){ id2 = j; } } // printf("id1 %s id2 %s\n", n1, n2); // printf("您查找的起始點和終點分別是: %s -> %s\n", n1, n2); if(id1 == -1 or id2 == -1){ printf("您輸入的名稱不存在!\n"); continue; } printf("您查找的起始點和終點分別是: %s -> %s\n", n1, n2); // 清空數組 memset(visit, 0, sizeof(visit)); // 可選路線數量 ansNum = 0; nowLu[0] = id1; // 放入起點 visit[id1] = 1; minPrict = 0x3f3f3f3f; // 初始化最優價格 dfs(id1, id2, 1, 0); // 起點, 終點, 路線中數據點個數, 價格 for(int i = 0; i < minCnt; i++){ if(i == 0) printf("最優路線:%s", names[minLu[i]]); else printf(" -> %s", names[minLu[i]]); printf("("); for(int j = 0; j < stations[minLu[i]].cnt; j++){ printf("%d,", stations[minLu[i]].lines[j]); } printf(")"); } printf(" [費用:%lf]\n", minPrict); printf("本次查找結束!!!\n\n"); } return 0; }
數據:
a b 4 b c 10 c d 7 d e 4 # f g 3 g c 8 c h 4 h i 1 i j 7 # k l 4 l m 7 m d 3 d n 2 n o 1 # p l 2 l q 1 q r 3 r s 5 s t 9 # u t 1 t v 9 v d 3 d w 7 w x 3 x y 2 #