• 动态规划实现最短路径问题


    一、设计最短路径的动态规划算法

      <算法导论>中一般将设计动态规划算法归纳为下面几个步骤:

      1)分析最优解的结构

      2)递归定义最优解的值

      3)自底向上计算最优解的值

      4)从计算的最优解的值上面构建出最优解

    二、最短路径的结构

      从最优解的结构开始分析(我们假设没有权值为负的路径),对于图G<V,E>的所有结点对最短路径的问题,我们能知道一条最短路径的子路径都是最短路径。假设用邻接矩阵W=w(ij)来表示输入带权图,考虑从结点i到结点j的一条最短路径p,如果p最多有m(m为有限值)条边。若i=j,则p的权值为0而且不包含其他边。若i ≠ j,可以将i到j的路径转换为i -> k、k->j。

    三、一个给定的图

      1)给定一个有向图

      

      2)我们可以给出这个有向图的邻接矩阵

      

    四、C++实现

      

      1 #include <iostream>
      2 #include<fstream>
      3 #include<sstream>
      4 #include<vector>
      5 #include<string>
      6 using namespace std;
      7 const int Max_Num = 100;
      8 
      9 typedef struct Point {
     10     int n; //点的个数 
     11     double p[Max_Num];
     12     double q[Max_Num]; 
     13     int root[Max_Num][Max_Num];
     14     double w[Max_Num][Max_Num];
     15     double e[Max_Num][Max_Num];
     16 }Point;
     17 
     18 vector<Point> points;
     19 vector<string> res;
     20 vector<int> num;
     21 
     22 void file_read();
     23 void createPoint();
     24 void optimalBST();
     25 void printRoot(Point P);
     26 void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite);
     27 template <class Type>
     28 Type stringToNum(const string& str) {
     29     istringstream iss(str);
     30     Type num;
     31     iss >> num;
     32     iss.str("");
     33     return num;
     34 }
     35 
     36 void file_read() {
     37     string str2, str1 = "", result;
     38     ifstream fileRead("in.dat");
     39     if (fileRead.is_open()) {
     40         while (getline(fileRead, str2, '
    ')) {
     41             if (str2.find(" ") != -1) {
     42                 str1.append(str2 + " ");
     43             }
     44             else {
     45                 num.push_back(stringToNum<int>(str2));
     46                 if (str1 != "") {
     47                     res.push_back(str1);
     48                 }
     49                 str1 = "";
     50             }
     51         }
     52         res.push_back(str1);
     53         fileRead.close();
     54     }
     55 }
     56 
     57 void createPoint() {
     58     string temp;
     59     Point P;
     60     for (int i = 0; i < res.size(); i++) {
     61         vector<string> temp_str; //存放按照空格分开后的数字 
     62         int n = num[i];
     63         stringstream input(res[i]); 
     64         while (input >> temp) {
     65             temp_str.push_back(temp);
     66         }
     67         P.n = n;
     68         for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]);
     69         for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]);
     70         points.push_back(P);
     71     }
     72 }
     73 
     74 //根据书上的伪代码:接收概率列表p1....pn和q0.....qn以及规模n作为输入  计算出e和root 
     75 void optimalBST(){
     76     Point P;
     77     for(int i = 0; i<res.size(); i++) {
     78         vector<string> temp_str; //存放按照空格分开后的数字 
     79         int n = num[i];
     80         string temp;
     81         stringstream input(res[i]); 
     82         while (input >> temp) {
     83             temp_str.push_back(temp);
     84         }
     85         P.n = n;
     86         
     87         for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]);
     88         for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]);
     89         
     90         //初始化只包括虚拟键的子树
     91         for (int i = 1;i <= P.n + 1;++i){
     92             P.w[i][i-1] = P.q[i-1];
     93             P.e[i][i-1] = P.q[i-1];
     94         }
     95         //由下到上,由左到右逐步计算
     96         for (int len = 1;len <= P.n;++len){
     97             for (int i = 1;i <= P.n - len + 1;++i){
     98                 int j = i + len - 1;
     99                 P.e[i][j] = Max_Num;
    100                 P.w[i][j] = P.w[i][j-1] + P.p[j] + P.q[j];
    101                 //求取最小代价的子树的根
    102                 for (int r = i;r <= j;++r)
    103                 {
    104                     double temp = P.e[i][r-1] + P.e[r+1][j] + P.w[i][j];
    105                     if (temp < P.e[i][j])
    106                     {
    107                         P.e[i][j] = temp;
    108                         P.root[i][j] = r;
    109                     }
    110                 }
    111             }
    112         }
    113         points.push_back(P);
    114     }
    115 }
    116 
    117 void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite){
    118     int root_node = P.root[i][j];//子树根节点
    119     if (root_node == P.root[1][P.n]){
    120         //输出整棵树的根
    121         fileWrite << "k" << root_node << "是根" << endl;
    122         printOptimalBST(i, root_node - 1, root_node, P, fileWrite);
    123         printOptimalBST(root_node +1 , j, root_node, P, fileWrite);
    124         return;
    125     }
    126  
    127     if (j < i - 1){
    128         return;
    129     }else if (j == i - 1){//遇到虚拟键
    130         if (j < r)
    131             fileWrite << "d" << j << "" << "k" << r << "的左孩子" << endl;
    132         else
    133             fileWrite << "d" << j << "" << "k" << r << "的右孩子" << endl;
    134         return;
    135     }
    136     else{//遇到内部结点
    137         if (root_node < r)
    138             fileWrite << "k" << root_node << "" << "k" << r << "的左孩子" << endl;
    139         else
    140             fileWrite << "k" << root_node << "" << "k" << r << "的右孩子" << endl;
    141     }
    142     printOptimalBST(i, root_node - 1, root_node, P, fileWrite);
    143     printOptimalBST(root_node + 1, j, root_node, P, fileWrite);
    144 }
    145 
    146 //输出最优二叉查找树所有子树的根
    147 void printRoot(Point P){ 
    148     cout << "各子树的根:" << endl;
    149     for (int i = 1;i <= P.n;++i){
    150         for (int j = 1;j <= P.n;++j){
    151             cout << P.root[i][j] << " ";
    152         }
    153         cout << endl;
    154     }
    155     cout << endl;
    156 }
    157  
    158 int main(){
    159     file_read();
    160     optimalBST();
    161     ofstream fileWrite("out.dat");
    162     Point P ;
    163     for(int i = 0; i<points.size(); i++) {
    164         P = points[i];
    165         printRoot(P);
    166         printOptimalBST(1,P.n,-1, P, fileWrite);
    167     }
    168     fileWrite.clear();
    169     return 0;
    170 }

       上述代码是将给定的邻接矩阵从文件中读取

        

        然后根据输入的邻接矩阵求出最短路径

        

  • 相关阅读:
    VKD224B触摸芯片调试笔记
    liunx 常用命令学习笔记
    2440 裸机学习 点亮LED
    单端正激变换器
    c# 文件与流
    c# 接口笔记
    Ubuntu18.04 server安装步骤
    how to force git to overwritten local files
    Linux基础
    解决Linux下Firefox无法启动的问题
  • 原文地址:https://www.cnblogs.com/fsmly/p/10046771.html
Copyright © 2020-2023  润新知