题目原文链接:点击打开链接
翻译题目要求:
程序的输入:第一行包含4个整数,用空格分开,分别代表城市的数量N、道路的数量M、当前出发的城市序号C1、目的地城市序号C2;第二行需要输入N个整数,用空格分开,顺序代表每个城市拥有的救援人员数量;接下来需要输入M行,每行包括3个整数描述道路信息,分别是 道路起点序号、道路另一起点序号、道路长度,用空格分隔。
程序的输出:计算出C1到C2之间最短距离的数目、可以得到救援人员的最大数量(单个道路内)。
设计思路如下:
通过输入创建图矩阵后,使用Floyd算法算出最短路径的同时,使用辅助数组记录每对两点之间存在相同距离的case,最后通过Floyd的path数组和辅助数组,计算出C1到C2的距离和途径。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
#define MatrixSize 100
#define INFINITE 65535
typedef int WeightType;
typedef int VertexType;
typedef struct tagGraph
{
VertexType point[MatrixSize]; //顶点value数组
WeightType matrix[MatrixSize][MatrixSize]; //路径权重矩阵表
int vertexNumber; //顶点数量
int edgeNumber; //路径数量
}Graph,*pGraph;
typedef struct tagFindSamePath
{
tagFindSamePath()
{
findHead = -1;
findEnd = -1;
findMid = -1;
findListIndex = 0;
}
void Reset()
{
findHead = -1;
findEnd = -1;
findMid = -1;
}
int findHead; //在已有队列中发现多路的起始点序号
int findEnd; //在已有队列中发现多路的终点序号
int findMid; //新的起始点和终点的第一个后继点实值,插入到新的队列中
int findListIndex; //目标已有队列序号
}SamePath,*pSamePath;
typedef struct tagPathList
{
tagPathList()
{
size = 0;
list = NULL;
distance = NULL;
}
int** list;
int size;
int* distance;
}PathList,*pPathList;
int* path = NULL;
int* distanceMatrix = NULL;
int* samePath = NULL;
Graph graph;
PathList avalPath;
vector<SamePath> SamePathRecord;
int CreateGraph( Graph* p)
{
int v1,v2,distance;
for ( int i = 0; i < p->vertexNumber; i++ )
{
for ( int j = 0; j < p->vertexNumber; j++ )
{
if ( i == j ) p->matrix[i][j] = 0;
else p->matrix[i][j] = INFINITE;
}
}
for ( int i = 0; i < p->edgeNumber; i++ )
{
printf("Please Input the pair of two cities and their Distance:\n");
getchar();
scanf("%d %d %d", &v1, &v2, &distance );
p->matrix[v1][v2] = distance;
p->matrix[v2][v1] = distance;
}
return 0;
}
int PrintMatrixResult( Graph* p )
{
for ( int i = 0; i < p->vertexNumber; i++ )
{
for ( int j = 0; j < p->vertexNumber; j++ )
{
printf( "%d ",p->matrix[i][j] );
}
printf("\n");
}
return 0;
}
void ParseValueOfPoint( Graph* graph, char* buf )
{
int index = 0;
char buffer[200] = {0};
strcpy( buffer, buf );
char* p = buffer;
p = strtok( buffer, " " );
while ( p != NULL )
{
graph->point[index++] = atoi( p );
p = strtok( NULL, " " );
}
}
void Floyd( Graph* graph )
{
int size = graph->vertexNumber;
int used = 0;
path = (int*)malloc( size*size*sizeof(int) + 1 );
distanceMatrix = (int*)malloc( size*size*sizeof(int) + 1 );
samePath = (int*)malloc( 3*size*sizeof(int) );
for( int i = 0; i < size; i++ )
for( int j = 0; j < size; j++ )
{
*(distanceMatrix+ i*size + j) = graph->matrix[i][j];
*(path + i*size + j) = j;
}
for( int k = 0; k < size; k++ )
for( int i = 0; i < size; i++ )
for( int j = 0; j < size; j++ )
{
if ( i == j || ( i == k || j == k ) )
{
continue;
}
int c = *( distanceMatrix + i*size + j );
int c1 = *( distanceMatrix + i*size + k );
int c2 = *( distanceMatrix + k*size + j );
if( c1 > 0 && c1 < INFINITE
&& c2 > 0 && c2 < INFINITE
&& c >= c1 + c2 )
{
if( c == c1 + c2 )
{
samePath[used++] = i;
samePath[used++] = j;
samePath[used++] = k;
}
else
{
*(distanceMatrix + i*size + j) = c1 + c2;
*(path + i*size + j ) = *(path + i*size + k);
}
}
}
samePath[used] = INFINITE;
}
// 在指定的一段缓冲区数组里查找 目标value的位置序号
int findValueFromArray( int* array, int value )
{
int bFind = -1;
for ( int i = 0; ; i++ )
{
if ( array[i] == INFINITE )
{
break;
}
if ( array[i] == value )
{
bFind = i;
break;
}
}
return bFind;
}
// 寻找现在发现的新路是否和以前的情况一致
int findConflictSamePath( int head, int end, int mid, int listIndex )
{
int size = SamePathRecord.size();
for ( int iLoop = 0; iLoop < size; iLoop++ )
{
SamePath path = SamePathRecord[iLoop];
if ( head == path.findHead && end == path.findEnd && mid == path.findMid && listIndex == path.findListIndex )
{
return true;
}
}
return false;
}
// 在已有的路径中根据same表 寻找新路
int FindSamePath( SamePath& path )
{
for ( int i = path.findListIndex; i < avalPath.size; i++ )
{
int* tempList = avalPath.list[i];
for ( int j = 0; ; j++ )
{
if ( tempList[j] == INFINITE )
{
break;
}
for ( int k = 0; ; k += 3 )
{
if ( samePath[k] == INFINITE )
{
break;
}
if ( tempList[j] == samePath[k] )
{
path.findEnd = findValueFromArray( tempList+(j+1), samePath[k+1] );
path.findMid = findValueFromArray( tempList + (j+1), samePath[k+2] );
if ( path.findEnd != -1 && path.findMid == -1 )
{
path.findHead = j; //记录目标队列里的i
path.findEnd = j+1+path.findEnd; //记录目标队列里的j
path.findMid = samePath[k+2]; //记录same表中的k
path.findListIndex = i; //记录目标队列所在的序号
// 和以前匹配的记录要不一致才可以视为新路
if ( findConflictSamePath( path.findHead, path.findEnd, path.findMid, path.findListIndex ) == false )
{
SamePathRecord.push_back( path );
return true;
}
else continue;
}
else
{
continue;
}
}
}
}
}
return false;
}
// 发现新路径后,依据FindSamePath结构体 在路径数组里面追加上来
int AppendNewPath( Graph* graph, SamePath path )
{
int size = graph->vertexNumber;
int* AimList = avalPath.list[path.findListIndex];
int* tempList = (int*)malloc( size*sizeof(int) );
int used = 0;
for ( int i = 0; ; i++ )
{
if ( AimList[i] == INFINITE )
{
break;
}
if ( i != path.findHead )
{
tempList[used++] = AimList[i];
}
else if ( i == path.findHead )
{
tempList[used++] = AimList[path.findHead];
tempList[used++] = path.findMid;
tempList[used++] = AimList[path.findEnd];
i = path.findEnd;
}
}
tempList[used] = INFINITE;
avalPath.list[avalPath.size++] = tempList;
return true;
}
int CalcMaxNumber()
{
int size = graph.vertexNumber;
int maxNumber = 0;
avalPath.distance = (int*)malloc( size*sizeof(int) );
for ( int i = 0; i < avalPath.size; i++ )
{
int* temp = avalPath.list[i];
int sum = 0;
for ( int j = 0; ; j++ )
{
if ( temp[j] == INFINITE )
{
break;
}
if ( temp[j] != INFINITE )
{
sum += graph.point[temp[j]];
}
}
avalPath.distance[i] = sum;
}
avalPath.distance[avalPath.size] = INFINITE;
// 计算出最大的
for ( int k = 0; k < avalPath.size; k++ )
{
if ( maxNumber < avalPath.distance[k] )
{
maxNumber = avalPath.distance[k];
}
}
return maxNumber;
}
// 算出所有可到达、符合条件的路径
void CollectPath( Graph* graph, int current, int dest )
{
int size = graph->vertexNumber;
int temp = current;
int* vertexList = (int*)malloc( size*sizeof(int) );
int used = 0;
while ( temp != dest )
{
printf( "%d City has value:%d\n",temp,graph->point[temp] );
vertexList[used++] = temp;
temp = *( path + temp*size + dest );
}
vertexList[used++] = dest;
vertexList[used] = INFINITE;
avalPath.list = (int**)malloc( size*sizeof(int*) );
avalPath.list[avalPath.size++] = vertexList;
SamePath samePath;
int result = FindSamePath(samePath);
while( result )
{
AppendNewPath(graph,samePath);
//新路径追加完毕后继续探索,如有,循环继续追加
samePath.Reset();
result = FindSamePath(samePath);
}
printf( "the path length is %d and has %d emergency\n", *( distanceMatrix + current*size + dest ), CalcMaxNumber() );
for ( int i = 0; i < avalPath.size; i++ )
{
free(avalPath.list[i]);
}
}
int main()
{
int currentCity = 0;
int destCity = 0;
char buffer[200] = {0};
printf("Please Input the Number of Cityies/the Number of path/\nyour Current City/your Destination:\n");
scanf("%d %d %d %d", &graph.vertexNumber, &graph.edgeNumber, ¤tCity, &destCity );
printf("Please Input the Number of Emergency Rescue in Every City:\n");
getchar();
scanf("%[^\n]",buffer);
ParseValueOfPoint( &graph, buffer );
CreateGraph(&graph);
PrintMatrixResult(&graph);
Floyd(&graph);
CollectPath( &graph, currentCity, destCity );
free(path);
free(distanceMatrix);
free(samePath);
printf("\n");
return 0;
}
算法还有很大优化的余地,。。。写的过程很是捉急,智商用光了。