トピック:ある企業が、ある地域に 6 つの製品販売拠点を持ち、販売拠点間の距離を下の図に示します。現在、ビジネスのニーズに応じて、販売拠点の 1 つに中央倉庫を設置し、他の販売拠点に製品を提供することを計画しています。
商品を各販売拠点に 1 日 1 回輸送する必要があり、1 回の出荷で 1 つの販売拠点しか供給できないと仮定すると、総輸送距離が最短になるように中央倉庫をどこに構築すればよいでしょうか。最短の輸送距離を見つけます。
アイデア:
これは、グラフの中心頂点を見つける問題です。つまり、重み付きグラフ G で、v から他の頂点までの最短経路長の合計が最小になるような頂点 v を見つけます。最初にフロイド アルゴリズムを使用して、グラフ内の各頂点間の最短経路長を見つけ、次に各頂点から他の頂点までの最短経路長の合計を見つけ、最短経路長の合計が最小の頂点を次のように選択します。要件の頂点。
各頂点の最短距離:
あ | B | C | D | え | ふ | 和 | |
---|---|---|---|---|---|---|---|
あ | \ | 2 | 3 | 5 | 10 | 3 | 23 |
B | 2 | \ | 2 | 4 | 10 | 5 | 23 |
C | 3 | 2 | \ | 2 | 8 | 6 | 21 |
D | 5 | 4 | 2 | \ | 10 | 8 | 29 |
え | 10 | 10 | 8 | 10 | \ | 7 | 45 |
ふ | 3 | 5 | 6 | 8 | 7 | \ | 29 |
上図の隣接行列表現 ("∞" は切断されていることを意味します)
実装コード + コメント
# include<stdio.h>
# define VERTEX_NUM 6 //顶点个数
# define INFINITY 32768
/*图的邻接矩阵表示法*/
typedef struct {
char vertex[VERTEX_NUM]; //顶点
int arcs[VERTEX_NUM][VERTEX_NUM]; //邻接矩阵
int vexnum, arcnum; //图的顶点数和弧数
}AdjMatrix;
/*根据题中信息创建无向网*/
int CreateDN(AdjMatrix* G) {
int i, j;
G->vexnum = 6; //共有6个销售点即图顶点数为6
G->arcnum = 8; //共有8条路径即图的弧数为8
for (i = 0; i < G->vexnum; i++)
G->vertex[i] = 'A' + i;
for (i = 0; i < G->vexnum; i++) {
//初始化邻接矩阵
for (j = 0; j < G->vexnum; j++)
G->arcs[i][j] = INFINITY;
}
G->arcs[0][1] = 2; //建立邻接矩阵
G->arcs[0][2] = 3;
G->arcs[0][4] = 10;
G->arcs[0][5] = 3;
G->arcs[1][2] = 2;
G->arcs[2][3] = 2;
G->arcs[2][4] = 8;
G->arcs[4][5] = 7;
G->arcs[1][0] = 2;
G->arcs[2][0] = 3;
G->arcs[4][0] = 10;
G->arcs[5][0] = 3;
G->arcs[2][1] = 2;
G->arcs[3][2] = 2;
G->arcs[4][2] = 8;
G->arcs[5][4] = 7;
}
/*求图的中心顶点算法*/
void CenterVex(AdjMatrix G) {
int i, j, k, min, len;
int A[VERTEX_NUM][VERTEX_NUM]; //A[i][j]存放顶点i和j之间的最短路径长度
for (i = 0; i < VERTEX_NUM; i++) {
//初始化A[i][j]
for (j = 0; j < VERTEX_NUM; j++)
A[i][j] = G.arcs[i][j];
A[i][i] = 0; //i到i的路径长度为0
}
for (k = 0; k < VERTEX_NUM; k++) {
//求出每一对顶点之间的最短路径长度(Floyd算法核心)
for (i = 0; i < VERTEX_NUM; i++) {
for (j = 0; j < VERTEX_NUM; j++) {
if (A[i][k] + A[k][j] < A[i][j])
A[i][j] = A[i][k] + A[k][j];
}
}
}
min = INFINITY;
k = 0;
for (i = 0; i < VERTEX_NUM; i++) {
//选择到各顶点最短路径长度之和最小的顶点vk
len = 0;
for (j = 0; j < VERTEX_NUM; j++) //求vi到其余各顶点的最短路径长度之和
len = len + A[i][j];
if (len < min) {
k = i;
min = len;
}
}
printf("建在%c处\n最短运输总距离为%d\n", G.vertex[k], min);
}
int main() {
AdjMatrix G;
CreateDN(&G);
CenterVex(G);
return 0;
}
操作結果: