动态规划--多段图最短路径

来源:互联网 发布:adsl拨号软件 编辑:程序博客网 时间:2024/05/16 19:38

问题描述:设是一个赋权有向图,其顶点集V被划分为个不相交的子集,其中,V1和Vk分别只有一个顶点s(称为源)和一个顶点t(称为汇),所有的边(u,v)的始点和终点都在相邻的两个子集Vi和Vi+1中:, 且边(u,v)有一个正权重,记为.请设计一个算法,求解从源s到汇t的权重之和最小的路径。


状态表示

包含源s的子图都可以认为是一个子问题,子图的源是固定的,汇是可以变化的。因此,确定了汇的位置,则能确定一个子图。汇的位置包括两个参数:段的序号和该段顶点集合中汇顶点的序号。

W(i,p)表示从源s 到v(i,p) 的最短路径长度

ui(1≤i≤k)表示段的序号
up(1≤p≤n_i)表示第 i 段顶点集中的顶点序号


状态递推方程


最优值求解

u子问题的数目等于图G中顶点的个数
u采用自底向上的方法求最优值,最开始求解源s到第2段顶点集中每一个顶点的最短路径。这是最简单的子问题,最优值就等于边长。

然后求解s到第3段顶点集中的每一个顶点的最优值,依此循环,直至求解s到t的最短路径值


输入:包含多组测试数据。每组测试数据第一行输入正整数k(k<100), 表示不相交子集的数目。第二行包含k个正整数ni(1<=i<=k),分别表示每一个顶点集Vi(1<=i<=k)中顶点的数目(不超过100)。紧接着k-1行记录相邻顶点集合间边的权重。其第i(1<=i<k)行包含niXni+1个数,表示顶点集Vi和Vi+1之间的边的权重(-1表示没有边相连),权重矩阵按行排列,也就是Vi中第p(1<=p<ni)个顶点和Vj中第q(1<=q<ni)个顶点之间的权重对应行第(p-1)Xnj+q和位置的值。最后一行输入-1,表示输入结束。


输出:每组测试数据的结果输出占一行,输出其最小的权重值。


样例输入:

5

1 4 3 3 1

9 7 3 2

4 2 1 2 7 -1 -1 -1 11 -1 11 8

6 5 -1 4 3 -1 -1 5 6

4 2 5 

-1

程序如下:

[cpp] view plain copy
print?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define MaxState 100  
  5.   
  6. int minRoad[MaxState][MaxState];  
  7. void multiStageGraph(int stageNum, int *numPerStage);  
  8.   
  9. int main()  
  10. {  
  11.     int i, k, ni[MaxState];  
  12.     while(scanf(“%d”, &k),k != -1)  
  13.     {  
  14.         for(i = 0; i < k; ++i)  
  15.         {  
  16.             scanf(”%d”, &ni[i]);  
  17.         }  
  18.         multiStageGraph(k, ni);  
  19.     }  
  20.     return 0;  
  21. }  
  22.   
  23. void multiStageGraph(int stageNum, int *numPerStage)  
  24. {  
  25.     int i, q, p, weight, temp;  
  26.     memset(minRoad, 0x3f, sizeof(minRoad));           //初始化为一个充分大的数0x3f  
  27.   
  28.     for (p = 0; p < numPerStage[0]; ++p)              //初始化源顶点层  
  29.     {  
  30.         minRoad[0][p] = 0;  
  31.     }  
  32.   
  33.     for (i = 0; i < stageNum - 1; ++i)                //按段计算,终止与汇顶点的前一段  
  34.     {  
  35.         for (q = 0; q < numPerStage[i]; ++q)          //遍历第i段顶点  
  36.         {  
  37.             for (p = 0; p < numPerStage[i + 1]; ++p)  //遍历第i+1段顶点  
  38.             {  
  39.                 scanf(”%d”, &weight);                 //读取边(q,p)的权重w(q,p)  
  40.                 if (weight != -1)                     //存在边(q,p)  
  41.                 {  
  42.                     temp = minRoad[i][q] + weight;  
  43.                     if (temp < minRoad[i+1][p])       //发现s到o的更短路径  
  44.                     {  
  45.                         minRoad[i+1][p] = temp;  
  46.                     }  
  47.                 }  
  48.             }  
  49.         }  
  50.     }  
  51.     printf(”%d\n”, minRoad[stageNum-1][0]);  
  52. }  
#include <stdio.h>
#include <stdlib.h>#define MaxState 100int minRoad[MaxState][MaxState];void multiStageGraph(int stageNum, int *numPerStage);int main(){ int i, k, ni[MaxState]; while(scanf("%d", &k),k != -1) { for(i = 0; i < k; ++i) { scanf("%d", &ni[i]); } multiStageGraph(k, ni); } return 0;}void multiStageGraph(int stageNum, int *numPerStage){ int i, q, p, weight, temp; memset(minRoad, 0x3f, sizeof(minRoad)); //初始化为一个充分大的数0x3f for (p = 0; p < numPerStage[0]; ++p) //初始化源顶点层 { minRoad[0][p] = 0; } for (i = 0; i < stageNum - 1; ++i) //按段计算,终止与汇顶点的前一段 { for (q = 0; q < numPerStage[i]; ++q) //遍历第i段顶点 { for (p = 0; p < numPerStage[i + 1]; ++p) //遍历第i+1段顶点 { scanf("%d", &weight); //读取边(q,p)的权重w(q,p) if (weight != -1) //存在边(q,p) { temp = minRoad[i][q] + weight; if (temp < minRoad[i+1][p]) //发现s到o的更短路径 { minRoad[i+1][p] = temp; } } } } } printf("%d\n", minRoad[stageNum-1][0]);}




原创粉丝点击