
大致思路:
将地铁线路的抽象问题转化为图上最短路径的具体问题,那么最大的难点如何抽象出来。
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 #
浙公网安备 33010602011771号