原题摘录-初步分析
通读之后,大致意思就是就是让你求出一条最长的高度连续降低的路径,且只能往与他本身相邻的路径上走.
仔细阅读-进一步理解题意
第二遍读题,更深入的理解问题,其实就是获得更加细节的问题,往相邻的方向上走就是往上下左右四个方向上走.而且若同时存在几个可选择的方向时,我们选择那个下落高度比较小的,因为这样能尽可能保证走的步数比较多.
这样的话,我们是不是考虑需要用到排序,那是不是按高度排序呢?从大到小还是最小到大呢?暂时应该有这样的想法出现.
决胜之战-确定数据结构和算法
到了这里,相信不用看题目,别人问你这个题的意思,也能给他以自己的理解方式复述一遍.
但是,这一步也是将自己的理解转化为计算机思维的一步,所以比较不易.
首先,我们发现每个滑雪点都有横坐标位置,纵坐标位置,和高度这三个属性.
因此,我们选用包含三个属性的结构体platform(平台的意思,起名字要有实际意义).
struct ski{
int x;//横坐标
int y;//纵坐标
int h;//高度
bool operator<(const ski &f)const//按高度排序的比较函数,从小到大
{
return h<f.h;
}
}s[10100];
试想,要计算最长滑行距离,是不是从较低的高度一次次通过计算最优叠加上来的.为将问题简化,假设只有五个高度,10,8,6,4,2且10可以到8,8可以到6…以此类推4可以到2,2没路可走了.我们如果想算出从10出发最长滑行的距离,因为10可以到8,那我们是不是需要算出从8出发的最长滑行距离.同样最后到2,发现是1.
所以说,要想求大,必先求小.这是一种从低到高的递推思路.
这时候,我们已经确定需要对结构体的高度进行排序.
大家有兴趣可以看一下上一篇文章动态规划实战练习1,说的比较细致,这是第二篇所以简化了不少.相信一定会有收获!
编写伪代码-搭好框架
//以向上为例
移动后的横坐标=原始位置+0;
移动后的纵坐标=原始位置+1;
if(移动后的位置没有越界且高度比原来小) {
重新记录经过此位置时的最长滑行距离
}
正式编程-测试完善
#include <bits/stdc++.h>
using namespace std;
int h,l;
int dp[102][102];
int hh[102][102];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//巧妙解决方向的问题
struct ski
{
int x;
int y;
int h;
bool operator<(const ski &f)const
{
return h<f.h;
}
}s[10100];
int main()
{
cin>>h>>l;
int r=0;
int ans=1; //初始最长滑行距离,最小为1
for(int i=1;i<=h;i++)
{
for(int j=1;j<=l;j++)
{
cin>>hh[i][j];
dp[i][j]=1;//初始值均赋值为1,因为一个点,到不了任何地方的时候,距离就是他自己1.
s[r].x=i;
s[r].y=j;
s[r].h=hh[i][j];//记录每个点对应的三个属性
r++;
}
}
sort(s,s+r);
for(int i=0;i<=r-1;i++)
{
int x=s[i].x;
int y=s[i].y;
for(int j=0;j<4;j++)
{
int xx=x+dir[j][0];
int yy=y+dir[j][1];
if(xx>=1&&xx<=h&&yy>=1&&yy<=l&&hh[x][y]>hh[xx][yy])//判定是否越界,满足条件
{
dp[x][y]=max(dp[x][y],dp[xx][yy]+1);//记忆型,记录该点的最长滑行距离,为下一个点(比他高的点)做数据准备
ans=max(ans,dp[x][y]);//更新数据
}
}
}
cout<<ans<<endl;
return 0;
}
如果还有不理解的地方,可在下方评论区留言,会在看到后第一时间回复.手打不易,在线求赞!