
大致思路:
將地鐵線路的抽象問題轉化為圖上最短路徑的具體問題,那么最大的難點如何抽象出來。
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 #
