给定一个有向无环图$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 <iostream>
#include <iomanip>
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! "<<endl;
cin>>numV;
}
this->numV=numV;
this->isWeighted=isWeighted;
this->isDirected=isDirected;
//private之后的成员可以被类的成员函数访问,但是不能够被使用该类的代码访问
matrix=new int *[numV];
for(int i=0;i<numV;i++)
matrix[i]=new int [numV];
//对图进行初始化
if(!isWeighted) //无权图
{
//对所有的权值初始化为0
for(int i=0;i<numV;i++)
for(int j=0;j<numV;j++)
matrix[i][j]=0;
}
else //有权图
{
for(int i=0;i<numV;i++)
for(int j=0;j<numV;j++)
matrix[i][j]=INITWEIGHT;
}
}
//建图
void graph::createGraph()
{
cout<<"input edges: "<<endl;
while(cin>>numE && numE<0)
cout<<"wrong input! "<<endl;
int i,j,w;
if(!isWeighted) //无权图
{
if(!isDirected) //无向图
{
cout<<"Input begin and end "<<endl;
for(int k=0;k<numE;k++)
{
cin>>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<<endl;
cin>>i>>j;
}
matrix[i][j]=matrix[j][i]=1;
}
}
else
{
cout<<"enter begin and end "<<endl;
for(int k=0;k<numE;k++)
{
cin>>i>>j;
while(!check(i,j))
{
cout<<"wrong edges, input again: "<<endl;
cin>>i>>j;
}
matrix[i][j]=1;
}
}
}
else //有权图
{
if(!isDirected) /