1.格路问题
!!复习算法考试所用,代码为老师课堂手写,逻辑没错,应该有点小问题,而且一看就莫得main函数,需要修改才能运行,仅供思路参考
欲求从左下角到右上角的最短路径
通过方法
使得r向右,u向上
1.r,r,r.....(m个),u,u,u,u,u,u(n个)
2.u,u,u,u,u,u(n个),r,r,r.....(m个)
一条路径为由m个r,n个u 构成的排列!共(m+n)!/(m!*n!)
蛮力做法构造(m+n)!/(m!+n!)个路径,需加法(m+n)!/(m!*n!)*(m+n-1)次,比较(m+n)!/(m!*n!)-1次
注:(m+n)!/(m!*n!) 为指数级别
下面为实现代码
template<class T>
struct TPoint{
T r,u;//向右,向上的距离
T d;//从0到此点的最短路径长
int from; // 0:无最短路径 1:左 2:右
TPoint():from(0),d(-1){}
};
ps: struct与class区别? 只有一点 声明默认等级不同 struct->public,class->private
分析:p.d= {
0 p为起点
L(p).d+L(p).r p为最底排
D(p).d+D(p).u p为最左排的列
min(L(p).d+L(p).r,D(p).d+D(p).u) 其他
初始化: int m=...,n=...;
TPoint<float> **g = new TPoint<float> *[m+1]; 实例化 行
for(int i = 0;i<=m;i++) 实例化 每个行上的列
{
g[i] = new TPoint<float>[n+1];
}
//至此 实例化出g[i][j] ; 0<=i<=m; 0<=j<=n;
//初始化二维表格
for(int i = 0;i<=m;i++)
{
for(int j = 0;j<=n;j++)
{
g[i][j].r = rand();
g[i][j].u = rand();
}
}
//DP方法(动态规划方法)
//1.先计算最简单的子问题
//最下一排
for(int i = 1;i<=m;i++)
{
g[i][0].d = g[i-1][0].d + g[i-1][0].r;
g[i][0].from = 1;//left
}
//最左一排
for(int j = 1;j<=n;j++)
{
g[0][j].d = g[0][j-1].d + g[0][j-1].u;
g[0][j].from = 2;//down
}
//自顶向上依次求解问题
for(int j = 1;j<=n;j++)
{
for(int i = 1;i<=m;i++)
{
//以下计算g[i][j]
//定义三个引用p,l,d
TPoint<float> &p = g[i][j];
TPoint<float> &L = g[i-1][j];
TPoint<float> &D = g[i][j-1];
float dL = L.d + L.r;
float dD = D.d + D.u;
if(dL<dD)
{
p.d = dL;
p.from = 1;//left
}
else{
p.d = dD;
p.from = 2;//down
}
}
}
//构造解
//方法一,采用动态数组 stl 中的 vector
std::vector<char> v;
int i = m , j = n;
while(i>0||j>0)
{
TPoint<float> &P = g[i][j];
if(p.from == 1) //左侧
{
v.push_back('r');
i--;
}
else
{
v.push_back('n');
j--;
}
}
//打印解 //v[k-1],v[k-2].......v[0]
int k = v.size();
for(int i = k-1;i>=0;i--)
{
cout<<v[i];
}
//方法二 采用栈 stack
std::stack<char> s;
int i = m , j = n;
while(i>=0||j>=0)
{
if(g[i][j].from==1)//left
{
s.push('r');
i--;
}
else{
s.push('u');
j--;
}
}
//打印,依次出栈
while(!s.emptu())
{
cout<<s.top();
s.pop();
}
//!!!!来到了重点 c++没有自动的内存回收机制,要手动释放
//清理工作,释放内存
for(int i = 0;i<=m;i++)
{
delete[] g[i];
}
delete[] g;