给定一个有向无环图$G=(V,E)$,边权重为实数,给定图中的两个顶点$k,t$,设计动态规划算法,求从k到t的最长简单路径,子问题图是怎样的?算法的效率如何?
算法分析:
该问题不能够用贪心求解,假设从k出发,每一步取得weight最大的边,按这样的路径,并不能够保证能走到终点t。所以考虑动态规划算法。
该问题满足动态规划算法的两个特征:
一、最优子结构:
从k出发到t的最优路径,一定是$max(best , path , A_1 , to ,, t+weightA_0)$,其中$A0-->A1-->cdots t$和$B0-->B1-->cdots t$等等的诸多方案中的最优方案,构成了最优解。符合“剪贴”性质。
二、重叠子结构
有上面的公式可知,子问题:$A0-->A1-->cdots t$会被反复求解。
int q=weight[k][t];
for(int i=k+1;i<=t && weight[k][i];i++)
{
q=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r));
}
r[k]=q;
return q;
算法实现
Graphic_longest_path.h
#include
#include
using namespace std;
#define INITWEIGHT 0
//用矩阵实现图
class graph
{
private:
bool isWeighted; //是否带权?
bool isDirected; //是否有向?
int numV; //顶点数
int numE; //边数
int **matrix; //邻接矩阵
public:
graph(int numV,bool isWeighted=false,bool isDirected=false);
void createGraph();
~graph();
int getVerNums()
{
return numV;
}
int getEdgeNums()
{
return numE;
}
int **getWeight()
{
return matrix;
}
void setEdgeWeight(int beg,int end,int weight);
void printAdjacentMatrix();
//检查输入
bool check(int i,int j,int w=1);
};
//类的实现
graph::graph(int numV,bool isWeighted,bool isDirected)
{
while(numV<=0)
{
cout<<"Vertex is wrong! Please enter again! "<>numV;
}
this->numV=numV;
this->isWeighted=isWeighted;
this->isDirected=isDirected;
//private之后的成员可以被类的成员函数访问,但是不能够被使用该类的代码访问
matrix=new int *[numV];
for(int i=0;i>numE && numE<0)
cout<<"wrong input! "<>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<>i>>j;
}
matrix[i][j]=matrix[j][i]=1;
}
}
else
{
cout<<"enter begin and end "<>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<>i>>j;
}
matrix[i][j]=1;
}
}
}
else //有权图
{
if(!isDirected) //无向图
{
cout<<"enter begin, end, and weight: "<>i>>j>>w;
while(!check(i,j,w))
{
cout<<"wrong edges,input again: "<>i>>j>>w;
}
matrix[i][j]=matrix[j][i]=w;
}
}
else
{
cout<<"begin, end, and weight: "<>i>>j>>w;
while(!check(i,j,w))
{
cout<<"wrong edges, input again: "<>i>>j>>w;
}
matrix[i][j]=w;
}
}
}
}
graph::~graph() //析构函数
{
for(int i=0;i>beg>>end>>weight;
}
if(isDirected)
matrix[beg][end]=weight;
else
matrix[beg][end]=matrix[end][beg]=weight;
}
else
{
while(!check(beg,end,1))
{
cout<<"wrong input, input again: "<>beg>>end;
}
if(isDirected) //对邻接矩阵的值进行反转,重置,1变成0,0变成1
matrix[beg][end]=1-matrix[beg][end];
else
matrix[beg][end]=matrix[end][beg]=1-matrix[beg][end];
}
}
//输入检查
bool graph::check(int i,int j,int w)
{
if(i>=0 && i=0 && j0)
return true;
else
return false;
}
void graph::printAdjacentMatrix()
{
cout.setf(ios::left);
cout<
dynamic_longest_path.h
#include "Graphic_longest_path.h"
#include
#include
#define INFINITY 0x7fffffff
int max(int a,int b)
{
return a>b?a:b;
}
int Find_longest_path(int **weight,int numVertexes,int k,int t,vector &r) //寻找k到t的最短路径
{
if(r[k]>=0)
return r[k];
if(k==t)
{
int q=0;
r[k]=q;
return q;
}
else
{
int q=weight[k][t];
for(int i=k+1;i<=t && weight[k][i];i++)
{
q=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r));
}
r[k]=q;
return q;
}
}
int dynamic_longest_path(int **weight,int numVertexes,int k,int t)
{
vector r;
r.resize(numVertexes);
for(int i=0;i
Graphic_longest_path.cpp
#include "dynamic_longest_path.h"
#include
int main()
{
cout<<"AdjacentMatrix Graphic: "<>numV;
cout<<"Is weighted? 0(no), 1(yes) : ";
cin>>isWeighted;
cout<<"IS directed? 0(no), 1(yes) : ";
cin>>isDirected;
graph graph(numV,isWeighted,isDirected);
cout<<"This is a ";
isDirected ? cout<<"Directed " : cout<<"Undirected: ";
isWeighted ? cout<<"Weighted " <>k>>t;
int numVertex=graph.getVerNums();
int **weight_dynamic=graph.getWeight();
cout<<"test: ";
cout<>flag;
if(flag)
{
if(isWeighted)
{
cout<<"Enter edges--begin, end, and weight: "<>beg>>end>>weight;
graph.setEdgeWeight(beg,end,weight);
}
else
{
cout<<"Enter edges--begin, end: "<>beg>>end;
graph.setEdgeWeight(beg,end,1);
}
cout<<"Successed!"<
重构解
为了能够输出最短路径的方案,可以对解进行重构:
Graphic_longest_path.h
#include
#include
using namespace std;
#define INITWEIGHT 0
//用矩阵实现图
class graph
{
private:
bool isWeighted; //是否带权?
bool isDirected; //是否有向?
int numV; //顶点数
int numE; //边数
int **matrix; //邻接矩阵
public:
graph(int numV,bool isWeighted=false,bool isDirected=false);
void createGraph();
~graph();
int getVerNums()
{
return numV;
}
int getEdgeNums()
{
return numE;
}
int **getWeight()
{
return matrix;
}
void setEdgeWeight(int beg,int end,int weight);
void printAdjacentMatrix();
//检查输入
bool check(int i,int j,int w=1);
};
//类的实现
graph::graph(int numV,bool isWeighted,bool isDirected)
{
while(numV<=0)
{
cout<<"Vertex is wrong! Please enter again! "<>numV;
}
this->numV=numV;
this->isWeighted=isWeighted;
this->isDirected=isDirected;
//private之后的成员可以被类的成员函数访问,但是不能够被使用该类的代码访问
matrix=new int *[numV];
for(int i=0;i>numE && numE<0)
cout<<"wrong input! "<>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<>i>>j;
}
matrix[i][j]=matrix[j][i]=1;
}
}
else
{
cout<<"enter begin and end "<>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<>i>>j;
}
matrix[i][j]=1;
}
}
}
else //有权图
{
if(!isDirected) //无向图
{
cout<<"enter begin, end, and weight: "<>i>>j>>w;
while(!check(i,j,w))
{
cout<<"wrong edges,input again: "<>i>>j>>w;
}
matrix[i][j]=matrix[j][i]=w;
}
}
else
{
cout<<"begin, end, and weight: "<>i>>j>>w;
while(!check(i,j,w))
{
cout<<"wrong edges, input again: "<>i>>j>>w;
}
matrix[i][j]=w;
}
}
}
}
graph::~graph() //析构函数
{
for(int i=0;i>beg>>end>>weight;
}
if(isDirected)
matrix[beg][end]=weight;
else
matrix[beg][end]=matrix[end][beg]=weight;
}
else
{
while(!check(beg,end,1))
{
cout<<"wrong input, input again: "<>beg>>end;
}
if(isDirected) //对邻接矩阵的值进行反转,重置,1变成0,0变成1
matrix[beg][end]=1-matrix[beg][end];
else
matrix[beg][end]=matrix[end][beg]=1-matrix[beg][end];
}
}
//输入检查
bool graph::check(int i,int j,int w)
{
if(i>=0 && i=0 && j0)
return true;
else
return false;
}
void graph::printAdjacentMatrix()
{
cout.setf(ios::left);
cout<
longest_path_constitute.h
#include "Graphic_longest_path.h"
#include
#include
#define INFINITY 0x7fffffff
int max(int a,int b)
{
return a>b?a:b;
}
int Find_longest_path(int **weight,int numVertexes,int k,int t,vector &r,int *solution) //寻找k到t的最短路径
{
if(r[k]>=0)
return r[k];
if(k==t)
{
int q=0;
r[k]=q;
solution[k]=t;
return q;
}
else
{
int q=weight[k][t];
if(weight[k][t])
solution[k]=t;
for(int i=k+1;i<=t && weight[k][i];i++)
{
int tmp=max(q,weight[k][i]+Find_longest_path(weight,numVertexes,i,t,r,solution));
if(tmp>q)
{
q=tmp;
solution[k]=i;
}
}
r[k]=q;
return q;
}
}
int dynamic_longest_path(int **weight,int numVertexes,int k,int t,int *solution)
{
vector r;
r.resize(numVertexes);
for(int i=0;i ";
while(k!=t)
{
cout< ";
}
k=solution[k];
}
cout<
Graphic_longest_path.cpp
#include "longest_path_constitute.h"
#include
int main()
{
cout<<"AdjacentMatrix Graphic: "<>numV;
cout<<"Is weighted? 0(no), 1(yes) : ";
cin>>isWeighted;
cout<<"IS directed? 0(no), 1(yes) : ";
cin>>isDirected;
graph graph(numV,isWeighted,isDirected);
cout<<"This is a ";
isDirected ? cout<<"Directed " : cout<<"Undirected: ";
isWeighted ? cout<<"Weighted " <>k>>t;
int numVertex=graph.getVerNums();
int **weight_dynamic=graph.getWeight();
cout<<"test: ";
cout<>flag;
if(flag)
{
if(isWeighted)
{
cout<<"Enter edges--begin, end, and weight: "<>beg>>end>>weight;
graph.setEdgeWeight(beg,end,weight);
}
else
{
cout<<"Enter edges--begin, end: "<>beg>>end;
graph.setEdgeWeight(beg,end,1);
}
cout<<"Successed!"<