网站核查怎么抽查,网站做全局搜索,用文本文档做网站,创意设计服务是什么滑雪
题目描述
Michael喜欢滑雪#xff0c;这并不奇怪#xff0c;因为滑雪的确很刺激。可是为了获得速度#xff0c;滑的区域必须向下倾斜#xff0c;而且当你滑到坡底#xff0c;你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中的最长底滑坡。区域…滑雪
题目描述
Michael喜欢滑雪这并不奇怪因为滑雪的确很刺激。可是为了获得速度滑的区域必须向下倾斜而且当你滑到坡底你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中的最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一当且仅当高度减小。在上面的例子中一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上这是最长的一条。
关于输入
输入的第一行表示区域的行数R和列数C(1R,C500)。下面是R行每行有C个整数代表高度h0h1000000。
关于输出
输出最长区域的长度。
例子输入
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
例子输出
25
解题分析
起初一看觉得是一个用DFS深度优先搜索的题无疑了于是用一个go函数并遍历每个位置从每个位置开始搜索并时刻更新搜索的长度和保留最大值同时也合理地存储了当前位置下的长度并在其他搜索路径经过此处时判断长度是否要更小如果更小说明这是一种无效的情况可以提前退出减枝操作。于是有了下面的代码:
代码演示1
#include iostream
using namespace std;
int R,C,mountains[505][505],res[505][505];
int ans1,dx[]{-1,1,0,0},dy[]{0,0,-1,1};void go(int x,int y,int step){if(stepans){ansstep;}if(stepres[x][y]){return;}for(int i0;i4;i){int nxdx[i]x,nydy[i]y;if(nx0 nxR ny0 nyC mountains[nx][ny]mountains[x][y]){go(nx,ny,step1);}}res[x][y]step;return;
}int main(){scanf(%d%d,R,C);for(int i0;iR;i)for(int j0;jC;j){scanf(%d,mountains[i][j]);}for(int i0;iR;i)for(int j0;jC;j){go(i,j,1);}printf(%d,ans);return 0;
}
首先本代码在思路以及算法的实现上都不存在问题总的来说这是个正确的代码。不过它有个致命的缺陷就是在一些特定的情况下递归深度会过大从而导致栈溢出programerror实际上我们也许根本不用调用那么多栈。
于是来看动态规划的思路
我们假定dp[i][j]是从(i,j)位置开始寻找所能到达的最大长度我们可以发现dp[i][j]max(dp[x-1][y]1,dp[x1][y]1,dp[x][y-1]1,dp[x][y1]1)于是动态规划的转移方程就出来啦。当前位置所能递推的最大深度就是它周围格子所能递推的最大深度再1就可以了。
代码实现
#include iostream
using namespace std;
int R,C,mountains[505][505],dp[505][505];
int ans1,dx[]{-1,1,0,0},dy[]{0,0,-1,1};int go(int x,int y){if(dp[x][y]){return dp[x][y];}int step1;for(int i0;i4;i){int nxxdx[i],nyydy[i];if(nx0 nxR ny0 nyC mountains[nx][ny]mountains[x][y]){stepmax(step,go(nx,ny)1);}}return dp[x][y]step;
}int main(){scanf(%d%d,R,C);for(int i0;iR;i)for(int j0;jC;j){scanf(%d,mountains[i][j]);}for(int i0;iR;i)for(int j0;jC;j){ansmax(ans,go(i,j));}printf(%d,ans);return 0;
}