滑雪问题(dfs+dp)
题目引入
佑少喜欢上网冲浪。最近他在贴吧得知滑铲可以消灭老虎,于是决定每天都到山坡上练习滑铲。不过佑少还没学会反重力滑铲,所以滑的区域必须向下倾斜,而且当滑到坡底,他不得不再次走上坡。
为了帮助佑少延长滑铲时间,请你计算一个区域中最长的滑坡,区域由一个二维数组给出。
PS:已知一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。
代码实现及解析
//注意提议说的下降的最大高度是指最多经过了了几个点,而不是最大的高度差
#include<iostream>
#include<algorithm>
using namespace std;
int Move[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };//四个方向的相对位置
int r, c;//全局变量的矩阵宽和高
int map[201][201];//存储的高度
int dp[201][201];//二维dp
int ans = -1;
void dfs(int x, int y)//dfs即运用递归,一条道走到黑,直到走不动(达到返回条件),才返回,继续尝试其他的路
{
if (dp[x][y] > 1)//表示已经走过了这条路
return;//什么也不返回,作用相当于break
for (int i = 0; i < 4; i++)
{
int tx = x + Move[i][0];
int ty = y + Move[i][1];
if ((tx < r) && (tx >= 0) && (ty < c) && (ty >= 0) && (map[tx][ty] > map[x][y]))//判断是否已经越界或者是否在单调递减
{
dfs(tx, ty);//递归调用
dp[x][y] = max(dp[x][y],dp[tx][ty] + 1);//二维dp的动态转移方程;即可以找出每个点对应的可以下滑的最大点数
}
}
}
int main()
{
cin >> r >> c;//行&&列
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
cin >> map[i][j];//依次输入数据
dp[i][j] = 1;//给dp数组初始化
}
}
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
dfs(i, j);
ans = max(ans, dp[i][j]);//对dp矩阵里的每个点数取最大值,找出最大的下滑点数(即对每个点对应的最大下滑点数再取最大值)
}
}
cout << ans;
return 0;
}
emmm…就这些。。