目录
记忆化搜索
记忆化搜索=搜索的形式+动态规划的思想
记忆化搜索:通常用于解决包含大量重复计算的的动态规划问题。它的思想是在递归计算过程中缓存中间结果,以避免重复计算。当需要再次计算一个已经计算过的结果时,可以直接从记录的状态的数据结构中读取,从而节省计算时间。
具体来说,记忆化搜索通常分为两个步骤:
-
递归计算:通常采用深度优先搜索(DFS)的方式,对于每一个需要计算的状态,都通过递归的方式向下搜索,并记录中间状态结果。
-
记忆化:当计算某个状态时,首先检查是否已经有计算的状态结果。如果有,直接返回记录中的状态结果,否则继续递归计算。
空间换时间:需要额外的空间来存储中间状态结果来提高效率。
题目描述
给定一个 R 行 C列的矩阵,表示一个矩形网格滑雪场。矩阵中第 i 行第 j 列的点表示滑雪场的第 i 行第 j列区域的高度。一个人从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。下面给出一个矩阵作为例子:
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−2−1。在给定矩阵中,最长的滑行轨迹为 25−24−23−…−3−2−1,沿途共经过 25个区域。现在给定你一个二维矩阵表示滑雪场各区域的高度,请你找出在该滑雪场中能够完成的最长滑雪轨迹,并输出其长度(可经过最大区域数)。
输入格式
第一行包含两个整数 R和 C。接下来 R行,每行包含 C个整数,表示完整的二维矩阵。
输出格式
输出一个整数,表示可完成的最长滑雪长度。
数据范围
1≤R,C≤300,0≤矩阵中整数≤10000
输入样例:
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
关键词
R 行 C列的矩阵,从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。
一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。
最长滑雪轨迹。
分析
如果一个点高度比周围某个点高度小,则该点的出发的最长路径可能会被包含在另一个高于它的点的最长路径里,所以每次计算需记录该点状态。
设f[i][j]表示从i,j点出发的路径,f[i][j]的值表示路径的最大长度
从某个点开始枚举四个方向,设某个方向点f[a][b],如果i,j点高度大于a,b,则从ij出发的最长路径长度=从a,b出发的最长路径长度+i,j这个点,则f[i][j]=f[a][b]+1;
思维图
代码如下
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
const int N=310;
int f[N][N],g[N][N];
//左 上 右 下
int dpx[4]={-1,0,1,0},dpy[4]={0,1,0,-1};
//dfs+记忆化数组
int dp(int x,int y)
{
int &v=f[x][y];
//记忆作用,如果该位置被算过直接返回值
if(v!=-1) return v;
//刚开始所在区域的值初始化为1
v=1;
//枚举上下左右四个方向
for(int i=0;i<4;i++)
{
int a=x+dpx[i],b=y+dpy[i];
//如果g[x][y]>g[a][b]->表示从x,y出发滑到别的地方a,b
//如果g[x][y]<g[a][b]->表示从a,b出发滑到a,b这个地方
if(a>=1&&a<=n&&b>=1&&b<=m&&g[x][y]>g[a][b])
//递归搜索,记录状态结果
v=max(v,dp(a,b)+1);
}
return v;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[i][j];
//先初始化-1,代表这个位置答案没有被计算过
memset(f,-1,sizeof f);
int res=0;//0或1开始都可
//枚举每个位置找到最大值
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
res=max(res,dp(i,j));
cout<<res;
}
相关链接