简易的C语言地铁购票系统

大致思路:

将地铁线路的抽象问题转化为图上最短路径的具体问题,那么最大的难点如何抽象出来。

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:
", ++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]
", 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
 ", 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("
", 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("
");
	} 
//	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("
");
//	}
//	printf("
");
	// 打印矩阵:
//	for (int i = 0; i < staNum; i++){
//		for(int j = 0; j < staNum; j++){
//			printf("%lf ", map[i][j]);
//		}
//		printf("
");
//	} 
	
	fclose(fp);
	
	// 功能启动:
	while(1){
		// 输入需要查找的线路:
		char n1[30];
		char n2[30];
		int i, j;

		// 查找当前站点是否存在 
	    int id1 = -1, id2 = -1;
	    printf("请输入起始点和终点:
");
		scanf("%s %s", n1, n2);
		for(j = 0; j < staNum; j++){
			 if(strcmp(n1, names[j]) == 0){
			 	id1 = j;
			 }
//			 else{
//			 	printf("%s %s
", n1, names[j]);
//			 }
			 if(strcmp(n2, names[j]) == 0){
			 	id2 = j;
			 }
		}	 
//		printf("id1 %s id2 %s
", n1, n2);
//		printf("您查找的起始点和终点分别是: %s -> %s
", n1, n2);
    	if(id1 == -1 || id2 == -1){
    		printf("您输入的名称不存在!
"); 
    		continue;
    	}
    	printf("您查找的起始点和终点分别是: %s -> %s
", 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]
", minPrict);
    	printf("本次查找结束!!!

");
	} 
    
    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:
", ++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]
", 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
 ", 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("
", 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("
");
	} 
//	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("
");
//	}
//	printf("
");
	// 打印矩阵:
//	for (int i = 0; i < staNum; i++){
//		for(int j = 0; j < staNum; j++){
//			printf("%lf ", map[i][j]);
//		}
//		printf("
");
//	} 
	
	fclose(fp);
	
	// 功能启动:
	while(1){
		// 输入需要查找的线路:
		char n1[30];
		char n2[30];
		printf("请输入起始点和终点:
");
		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
", n1, names[j]);
//			 }
			 if(strcmp(n2, names[j]) == 0){
			 	id2 = j;
			 }
		}	 
//		printf("id1 %s id2 %s
", n1, n2);
//		printf("您查找的起始点和终点分别是: %s -> %s
", n1, n2);
    	if(id1 == -1 or id2 == -1){
    		printf("您输入的名称不存在!
"); 
    		continue;
    	}
    	printf("您查找的起始点和终点分别是: %s -> %s
", 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]
", minPrict);
    	printf("本次查找结束!!!

");
	} 
    
    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 #

  

原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/12931480.html