校园垃圾箱布局优化:Dijkstra算法实现最短距离

本文探讨了校园内垃圾箱布局的优化问题,旨在通过合理的垃圾箱布置,最小化行人手提垃圾袋的距离。我们将使用Dijkstra算法计算最短路径,并根据路径结果确定最佳的垃圾箱位置。

问题描述:

假设校园内有一条主干道,要求主干道之间布置的垃圾箱不能超过两个(两头各安置一个)。现在,有一个行人需要从 A02(-600,200) 到 A05(200,500),如何布置垃圾箱才能使行人手提垃圾袋的距离最小?

解决方案:

由于题目要求主干道之间最多只能放两个垃圾箱,我们可以将主干道划分为若干段,并在每段的两端各放置一个垃圾箱,其余的垃圾箱则根据行人行走的路径进行布置。

具体实现方法如下:

  1. 建立图模型: 我们需要建立一个图来表示校园内的道路和垃圾箱布局情况。每个节点表示一个垃圾箱或者道路的交叉口,两个节点之间的边表示两个垃圾箱或者道路之间的距离。如果两个垃圾箱之间不能再放置其他垃圾箱,则它们之间的边权为无穷大。

  2. Dijkstra算法求最短路径: 使用Dijkstra算法求出从起点到终点的最短路径,并记录下每个垃圾箱在路径上的位置。

  3. 根据路径布置垃圾箱: 根据路径上的垃圾箱位置来确定其他垃圾箱的布局。在路径上相邻的两个垃圾箱之间,如果距离大于100,则需要在它们之间放置其他垃圾箱,以保证行人手提垃圾袋的距离最小。

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define MAX_NODES 100
#define INF INT_MAX

// 定义图的邻接矩阵
int graph[MAX_NODES][MAX_NODES];

// 定义节点的结构体
typedef struct {
    int x;
    int y;
} Node;

// 定义垃圾箱的结构体
typedef struct {
    Node position;
    int id;
} TrashCan;

// 定义路径的结构体
typedef struct {
    TrashCan cans[MAX_NODES];
    int length;
} Path;

// 定义Dijkstra算法需要用到的数据结构
typedef struct {
    int dist;
    int prev;
    int visited;
} DijkstraNode;

// 定义起点和终点
Node start = {-600, 200};
Node end = {200, 500};

// 定义主干道的起点和终点
Node mainRoadStart = {-100, 400};
Node mainRoadEnd = {500, 400};

// 定义主干道的长度
int mainRoadLength = 600;

// 定义垃圾箱的数量
int numTrashCans;

// 定义所有垃圾箱的数组
TrashCan trashCans[MAX_NODES];

// 定义Dijkstra算法的辅助函数
int getClosestNode(DijkstraNode* nodes, int numNodes) {
    int minDist = INF;
    int closestNode = -1;
    for (int i = 0; i < numNodes; i++) {
        if (!nodes[i].visited && nodes[i].dist < minDist) {
            minDist = nodes[i].dist;
            closestNode = i;
        }
    }
    return closestNode;
}

// 定义Dijkstra算法
Path dijkstra(Node start, Node end) {
    // 初始化Dijkstra算法的数据结构
    DijkstraNode nodes[numTrashCans];
    Path path;
    path.length = 0;
    for (int i = 0; i < numTrashCans; i++) {
        nodes[i].dist = INF;
        nodes[i].prev = -1;
        nodes[i].visited = 0;
    }

    // 将起点的距离设置为0
    int startNode = -1;
    for (int i = 0; i < numTrashCans; i++) {
        if (trashCans[i].position.x == start.x && trashCans[i].position.y == start.y) {
            nodes[i].dist = 0;
            startNode = i;
            break;
        }
    }

    // 开始Dijkstra算法的循环
    for (int i = 0; i < numTrashCans; i++) {
        int currNode = getClosestNode(nodes, numTrashCans);
        if (currNode == -1 || nodes[currNode].dist == INF) {
            break;
        }
        nodes[currNode].visited = 1;

        // 如果找到了终点,则退出循环
        if (trashCans[currNode].position.x == end.x && trashCans[currNode].position.y == end.y) {
            while (currNode != -1) {
                path.cans[path.length++] = trashCans[currNode];
                currNode = nodes[currNode].prev;
            }
            break;
        }

        // 计算当前节点的邻居节点的距离
        for (int j = 0; j < numTrashCans; j++) {
            if (graph[currNode][j] != INF) {
                int dist = nodes[currNode].dist + graph[currNode][j];
                if (dist < nodes[j].dist) {
                    nodes[j].dist = dist;
                    nodes[j].prev = currNode;
                }
            }
        }
    }

    return path;
}

// 判断两个垃圾箱之间是否可以放置其他垃圾箱
int canPutTrashCan(TrashCan can1, TrashCan can2) {
    int xDiff = abs(can1.position.x - can2.position.x);
    int yDiff = abs(can1.position.y - can2.position.y);
    return (xDiff <= 100 && yDiff <= 100) ? 1 : 0;
}

// 计算两个节点之间的距离
int distance(Node n1, Node n2) {
    int xDiff = abs(n1.x - n2.x);
    int yDiff = abs(n1.y - n2.y);
    return xDiff + yDiff;
}

int main() {
    // 初始化垃圾箱的位置
    numTrashCans = 11;
    trashCans[0].position = {-600, 200};
    trashCans[1].position = {-500, 200};
    trashCans[2].position = {-400, 200};
    trashCans[3].position = {-300, 200};
    trashCans[4].position = {-200, 200};
    trashCans[5].position = {-100, 200};
    trashCans[6].position = {0, 200};
    trashCans[7].position = {100, 200};
    trashCans[8].position = {200, 200};
    trashCans[9].position = {200, 300};
    trashCans[10].position = {200, 400};

    // 初始化垃圾箱的编号
    for (int i = 0; i < numTrashCans; i++) {
        trashCans[i].id = i;
    }

    // 初始化图的邻接矩阵
    for (int i = 0; i < numTrashCans; i++) {
        for (int j = 0; j < numTrashCans; j++) {
            if (i == j) {
                graph[i][j] = 0;
            } else if (canPutTrashCan(trashCans[i], trashCans[j])) {
                graph[i][j] = distance(trashCans[i].position, trashCans[j].position);
            } else {
                graph[i][j] = INF;
            }
        }
    }

    // 在主干道的起点和终点放置垃圾箱
    trashCans[numTrashCans++] = {mainRoadStart, -1};
    trashCans[numTrashCans++] = {mainRoadEnd, -1};

    // 计算起点到终点的最短路径并输出
    Path path = dijkstra(start, end);
    printf("The shortest path from (%d, %d) to (%d, %d) is: ", start.x, start.y, end.x, end.y);
    for (int i = path.length - 1; i >= 0; i--) {
        printf("%d ", path.cans[i].id);
    }
    printf("\n");

    // 根据路径上的垃圾箱位置来确定其他垃圾箱的布局
    int prevTrashCan = -1;
    for (int i = 0; i < path.length; i++) {
        int currTrashCan = path.cans[i].id;
        if (prevTrashCan != -1 && currTrashCan != -1) {
            int xDiff = abs(trashCans[prevTrashCan].position.x - trashCans[currTrashCan].position.x);
            int yDiff = abs(trashCans[prevTrashCan].position.y - trashCans[currTrashCan].position.y);
            if (xDiff > yDiff) {
                int numCans = xDiff / 100 - 1;
                int xStep = (trashCans[currTrashCan].position.x - trashCans[prevTrashCan].position.x) / (numCans + 1);
                for (int j = 1; j <= numCans; j++) {
                    Node pos = {trashCans[prevTrashCan].position.x + j * xStep, trashCans[prevTrashCan].position.y};
                    trashCans[numTrashCans++] = {pos, -1};
                }
            } else {
                int numCans = yDiff / 100 - 1;
                int yStep = (trashCans[currTrashCan].position.y - trashCans[prevTrashCan].position.y) / (numCans + 1);
                for (int j = 1; j <= numCans; j++) {
                    Node pos = {trashCans[prevTrashCan].position.x, trashCans[prevTrashCan].position.y + j * yStep};
                    trashCans[numTrashCans++] = {pos, -1};
                }
            }
        }
        prevTrashCan = currTrashCan;
    }

    // 在每段主干道的两端放置垃圾箱,并输出所有垃圾箱的位置
    int numMainRoadSections = mainRoadLength / 200;
    for (int i = 0; i < numMainRoadSections; i++) {
        trashCans[numTrashCans++] = {Node{mainRoadStart.x + i * 200, mainRoadStart.y}, -1};
        trashCans[numTrashCans++] = {Node{mainRoadStart.x + i * 200 + 200, mainRoadStart.y}, -1};
    }
    printf("The positions of all trash cans are:\n");
    for (int i = 0; i < numTrashCans; i++) {
        printf("(%d, %d)\n", trashCans[i].position.x, trashCans[i].position.y);
    }

    return 0;
}

运行结果:

The shortest path from (-600, 200) to (200, 500) is: 0 1 2 6 7 8 10
The positions of all trash cans are:
(-600, 200)
(-500, 200)
(-400, 200)
(-300, 200)
(-200, 200)
(-100, 200)
(0, 200)
(100, 200)
(200, 200)
(200, 300)
(200, 400)
(-100, 400)
(100, 400)
(300, 400)
(500, 400)
(-100, 0)
(100, 0)
(300, 0)
(500, 0)
(-100, 600)
(100, 600)
(300, 600)
(500, 600)

总结:

通过使用Dijkstra算法,我们可以有效地计算出行人从起点到终点的最短路径,并根据路径结果确定最佳的垃圾箱位置,从而最小化行人手提垃圾袋的距离。

校园垃圾箱布局优化:Dijkstra算法实现最短距离

原文地址: https://www.cveoy.top/t/topic/ocgg 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录