• 7-6 选取医院建立的位置(C语言版详解)


    设a、b、c、d、e、f表示一个乡的6个村庄,弧上的权值表 示两村之间的距离。现要在这6个村庄中选择一个村庄建一所医院,问医院建在哪个村庄 才能使离医院最远的村庄到医院的距离最短?

    输入格式:

    输入的第一行为村庄个数
    输入的其他是多个存在组成网络的邻接矩阵表示

    输出格式:

    输出医院建立的位置

    输入样例:

    在这里给出一组输入。例如:

    1. 6
    2. 0 12 3 65535 9 10
    3. 12 0 65535 2 6 65535
    4. 3 65535 0 2 65535 6
    5. 65535 2 2 0 4 7
    6. 9 6 65535 4 0 4
    7. 10 65535 6 7 4 0

    输出样例:

    在这里给出相应的输出。例如:

    c
    

    代码长度限制

    16 KB

    时间限制

    400 ms

    内存限制

    64 MB

    解题思路:本体要求找到一个地点建医院,算出这个医院距离其它每个结点的最小距离,然后找到每个出发点这些最小距离中最远的那个作比较。找到最远距离最小的那个输出。

    由于要用到最小路径,需要迪杰斯特拉算法

    1.先对需要的东西进行定义

    1. #define bool char
    2. #define true 1
    3. #define false 0
    4. typedef char VerTexType; //字符型顶点数据类型
    5. typedef int ArcType; //边的权值类型为整型
    6. #define MVNum 100 //最大顶点数
    7. #define MaxInt 32767 //最大权值

    2.图的结构,由于题中已经将邻接矩阵给出,所以不需要我们来自行创建 

    1. //图的邻接矩阵存储表示
    2. typedef struct
    3. {
    4. VerTexType vexs[MVNum]; //顶点表
    5. ArcType arcs[MVNum][MVNum];//邻接矩阵
    6. int vexnum, arcnum; //节点数和边数
    7. }AMGraph;
    8. //输入题中给的邻接矩阵
    9. void Scanf(AMGraph* G, int n)
    10. {
    11. int i, j;
    12. for(i = 0; i < n; i++)
    13. for(j = 0; j < n; j++)
    14. scanf("%d", &G->arcs[i][j]);
    15. G->vexnum = n;
    16. }

    3.迪杰斯特拉算法,其中D数组存放了起点v0到其他各个点位的最短距离,找到最大值返回。

    算法简介:

    1.初始化:

        (1)创建S数组存放结点被选中的情况,选过为True,没选为False;初始化时先全部置为False。

        (2)创建D数组存放到达从起点出发,到达其他顶点的距离,根据路径的发展,更小的权值会替换大的权值。初始化时先把出发点v0到其他结点的边赋给D

        (3)创建Path数组存放每个结点的上一个结点(前置结点),通常用来遍历最短路径,本题虽然不需要用到,但还是写上了。 初始化时都置为-1代表没有边连接上一个。                   

        (4)开始时把出发点v0S[v0]改为True代表选过了,起点到自己的距离D[v0] = 0;

    2.找到各个最小路径

       (1)从第一个结点到最后一个结点都要找一次起点到它的最短路径,这是最外一层循环

       (2)在当前的D数组中找到最小权值的边,记录下来用以链接到该边连接的下一个结点 

       (3)把新选出结点的S数组置为True,并且将新结点带来的新路径(边)和之前的路径权值进行比较,比之前小就替换掉D数组中对应的值,再将新结点的前置结点设置为上一个结点。

    3.返回每组中最远值    

    1. int Dijkstra(AMGraph G, int v0)
    2. {
    3. //S放是否选中过,D放起点距离其他点的距离,path放前驱结点,n是顶点个数
    4. int S[6], D[6], Path[6];
    5. int n = 6, i, w, v;
    6. //初始化
    7. for(v = 0; v < n; v++)
    8. {
    9. S[v] = false; //先把S都置为未选中过
    10. D[v] = G.arcs[v0][v]; //把顶点距离其他结点的距离输入
    11. if(D[v] < MaxInt) Path[v] = v0; //如果v0到v有边,那就把v的前置结点写上
    12. else Path[v] = -1; //如果没边,就把前置结点设置为-1代表没有
    13. }
    14. S[v0] = true; //起点设为选中过
    15. D[v0] = 0; //起点到自己的距离为0
    16. //开始找最小距离
    17. int min;
    18. for(i = 1; i < n; i++)
    19. {
    20. min = MaxInt;
    21. for(w = 0; w < n; w++)
    22. {
    23. //没被选中 并且有边的 结点
    24. if(!S[w] && D[w] < min)
    25. {
    26. //就记录下结点的位置
    27. v = w;
    28. //并把它的权值暂存为最小权值
    29. min = D[w];
    30. }
    31. }
    32. //最小边的结点改为被选中
    33. S[v] = true;
    34. //从新选中的结点开始寻找,
    35. for(w = 0; w < n; w++)
    36. {
    37. //未被选中,并且从起始节点到目前能到达的结点的最小值
    38. if(!S[w] && D[v] + G.arcs[v][w] < D[w])
    39. {
    40. //总长度 = 之前长度的总和+到新结点的长度
    41. D[w] = D[v] + G.arcs[v][w];
    42. //新结点的前置结点设置
    43. Path[w] = v;
    44. }
    45. }
    46. }
    47. //找到每组最远的那个
    48. int max = 0;
    49. for(int s = 0; s < 6; s++)
    50. {
    51. if(max < D[s])
    52. max = D[s];
    53. }
    54. return max;
    55. }

    4.主函数,因为本体条件是固定的,所以很多地方的大小我便直接写了6。

    1. int main()
    2. {
    3. //输入
    4. AMGraph G;
    5. int n;
    6. scanf("%d",&n);
    7. Scanf(&G, n);
    8. int temp[6];
    9. int min = 0;
    10. //先把每组的最远距离搞出来
    11. for(int i = 0; i < 6; i++)
    12. {
    13. temp[i] = Dijkstra(G, i);
    14. }
    15. //找最远距离中最小的
    16. for(int i = 0; i < 6; i++)
    17. {
    18. if(temp[min]>temp[i])
    19. min = i;
    20. }
    21. //转换字符
    22. char name = (char)min+97;
    23. printf("%c",name);
    24. return 0;
    25. }

     5.全部代码

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <math.h>
    4. #define bool char
    5. #define true 1
    6. #define false 0
    7. typedef char VerTexType; //字符型顶点数据类型
    8. typedef int ArcType; //边的权值类型为整型
    9. #define MVNum 100 //最大顶点数
    10. #define MaxInt 32767 //最大权值
    11. //辅助数组,用来记录从顶点集到
    12. struct
    13. {
    14. VerTexType adjvex;
    15. ArcType lowcost;
    16. } closedge[MVNum];
    17. //图的邻接矩阵存储表示
    18. typedef struct
    19. {
    20. VerTexType vexs[MVNum]; //顶点表
    21. ArcType arcs[MVNum][MVNum];//邻接矩阵
    22. int vexnum, arcnum; //节点数和边数
    23. }AMGraph;
    24. //找到出发点得位置
    25. int LocateVex(AMGraph* G, VerTexType v)
    26. {
    27. for(int i = 0; i < G->vexnum; i++)
    28. {
    29. if(G->vexs[i] == v)
    30. return i;
    31. }
    32. return -1;
    33. }
    34. //输入题中给的邻接矩阵
    35. void Scanf(AMGraph* G, int n)
    36. {
    37. int i, j;
    38. for(i = 0; i < n; i++)
    39. for(j = 0; j < n; j++)
    40. scanf("%d", &G->arcs[i][j]);
    41. G->vexnum = n;
    42. }
    43. //测试用
    44. void Print(AMGraph G)
    45. {
    46. int i, j;
    47. for(i = 0; i < G.vexnum; i++)
    48. {
    49. for(j = 0; j < G.vexnum; j++)
    50. printf("%d ", G.arcs[i][j]);
    51. printf("\n");
    52. }
    53. }
    54. //从每个顶点出发,找最短路径
    55. int Dijkstra(AMGraph G, int v0)
    56. {
    57. //S放是否选中过,D放起点距离其他点的距离,path放前驱结点,n是顶点个数
    58. int S[6], D[6], Path[6];
    59. int n = 6, i, w, v;
    60. //初始化
    61. for(v = 0; v < n; v++)
    62. {
    63. S[v] = false; //先把S都置为未选中过
    64. D[v] = G.arcs[v0][v]; //把顶点距离其他结点的距离输入
    65. if(D[v] < MaxInt) Path[v] = v0; //如果v0到v有边,那就把v的前置结点写上
    66. else Path[v] = -1; //如果没边,就把前置结点设置为-1代表没有
    67. }
    68. S[v0] = true; //起点设为选中过
    69. D[v0] = 0; //起点到自己的距离为0
    70. //开始找最小距离
    71. int min;
    72. for(i = 1; i < n; i++)
    73. {
    74. min = MaxInt;
    75. for(w = 0; w < n; w++)
    76. {
    77. //没被选中 并且有边的 结点
    78. if(!S[w] && D[w] < min)
    79. {
    80. //就记录下结点的位置
    81. v = w;
    82. //并把它的权值暂存为最小权值
    83. min = D[w];
    84. }
    85. }
    86. //最小边的结点改为被选中
    87. S[v] = true;
    88. //从新选中的结点开始寻找,
    89. for(w = 0; w < n; w++)
    90. {
    91. //未被选中,并且从起始节点到目前能到达的结点的最小值
    92. if(!S[w] && D[v] + G.arcs[v][w] < D[w])
    93. {
    94. //总长度 = 之前长度的总和+到新结点的长度
    95. D[w] = D[v] + G.arcs[v][w];
    96. //新结点的前置结点设置
    97. Path[w] = v;
    98. }
    99. }
    100. }
    101. //找到每组最远的那个
    102. int max = 0;
    103. for(int s = 0; s < 6; s++)
    104. {
    105. if(max < D[s])
    106. max = D[s];
    107. }
    108. return max;
    109. }
    110. int main()
    111. {
    112. //输入
    113. AMGraph G;
    114. int n;
    115. scanf("%d",&n);
    116. Scanf(&G, n);
    117. int temp[6];
    118. int min = 0;
    119. //先把每组的最远距离搞出来
    120. for(int i = 0; i < 6; i++)
    121. {
    122. temp[i] = Dijkstra(G, i);
    123. }
    124. //找最远距离中最小的
    125. for(int i = 0; i < 6; i++)
    126. {
    127. if(temp[min]>temp[i])
    128. min = i;
    129. }
    130. //转换字符
    131. char name = (char)min+97;
    132. printf("%c",name);
    133. return 0;
    134. }

  • 相关阅读:
    数据驱动 vs 关键字驱动:对搭建UI自动化测试框架的探索
    Echarts直角坐标系x轴y轴属性设置大全
    Qt文件读写的天花板QFile和QTextStream搭配第二集
    python+requests+pytest+allure自动化框架
    分类预测 | Matlab实现PSO-BiLSTM粒子群算法优化双向长短期记忆神经网络的数据多输入分类预测
    9.Linux实操指令(压缩和解压缩指令)
    java进制与位运算
    Happy 1024
    开源项目DevStream v0.1.0 发布,打造灵活的 DevOps 工具链
    前端src中图片img标签资源的几种写法?
  • 原文地址:https://blog.csdn.net/weixin_63484669/article/details/125400524