动态规划实战练习2-滑雪

原题摘录-初步分析

原题摘录
通读之后,大致意思就是就是让你求出一条最长的高度连续降低的路径,且只能往与他本身相邻的路径上走.

仔细阅读-进一步理解题意

第二遍读题,更深入的理解问题,其实就是获得更加细节的问题,往相邻的方向上走就是往上下左右四个方向上走.而且若同时存在几个可选择的方向时,我们选择那个下落高度比较小的,因为这样能尽可能保证走的步数比较多.
这样的话,我们是不是考虑需要用到排序,那是不是按高度排序呢?从大到小还是最小到大呢?暂时应该有这样的想法出现.

决胜之战-确定数据结构和算法

到了这里,相信不用看题目,别人问你这个题的意思,也能给他以自己的理解方式复述一遍.
但是,这一步也是将自己的理解转化为计算机思维的一步,所以比较不易.
首先,我们发现每个滑雪点都有横坐标位置,纵坐标位置,和高度这三个属性.
因此,我们选用包含三个属性的结构体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;
}

如果还有不理解的地方,可在下方评论区留言,会在看到后第一时间回复.手打不易,在线求赞!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值