滑雪
| DFS | 递归 |DP|
此题有两种方式,一种为递归,一种为非递归的写法。我一开始用的是非递归的写法,就需要从最低点开始更新dp才不会出现要更新较高点时无法利用旁边较低点的dp数据。这样的代码长度较为冗长,且对空间利用率不高。
#include<iostream>
#include<algorithm>
using namespace std;
int m,n;
//m代表行,n代表列
struct pos{
int x;
int y;
int h;
};
pos p[10010];
int cnt = 0;
int h[110][110];
int dp[110][110];
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
bool is_valid(int x,int y,int cur_h){
if(x>=0&&x<=m-1&&y>=0&&y<=n-1&&h[x][y]<cur_h){
return true;
}
return false;
}
bool cmp(pos a,pos b){
return a.h<b.h;
}
int main(){
cin>>m>>n;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
pos temp;
cin>>h[i][j];
temp.h = h[i][j];
temp.x = i;
temp.y = j;
p[cnt++] = temp;
dp[i][j] = -1;
}
}
//还没标记的dp用-1,这样可以避免之后的计算错误
sort(p,p+cnt,cmp);
dp[p[0].x][p[0].y] = 1;
for(int i=1;i<cnt;i++){
int cur_x = p[i].x;
int cur_y = p[i].y;
int m_path = 1;
for(int k=0;k<4;k++){
int nx = cur_x+dx[k];
int ny = cur_y+dy[k];
if(is_valid(nx,ny,p[i].h)){
if(dp[nx][ny]+1>m_path){
m_path = dp[nx][ny]+1;
}
}
}
dp[cur_x][cur_y] = m_path;
}
int m_lenth = 1;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(m_lenth<dp[i][j]){
m_lenth = dp[i][j];
}
}
}
cout<<m_lenth<<endl;
return 0;
}
另一种方法是递归的写法。递归可以解决如何保证更新某点旁边已经更新正确的dp值,即:
dfs(高点) {
需要 dfs(低点) // 👈 递归会先去算低点
// 等低点算完才继续
}
总的代码为:
#include <iostream>
#include <cstring>
using namespace std;
int m, n;
int h[110][110];
int dp[110][110];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int dfs(int x, int y) {
// 如果已经计算过,直接返回
if (dp[x][y] != -1) return dp[x][y];
dp[x][y] = 1; // 当前点至少长度为1
// 尝试四个方向
for (int k = 0; k < 4; k++) {
int nx = x + dx[k];
int ny = y + dy[k];
// 检查边界和高度条件
if (nx >= 0 && nx < m && ny >= 0 && ny < n && h[nx][ny] < h[x][y]) {
dp[x][y] = max(dp[x][y], dfs(nx, ny) + 1);
}
}
return dp[x][y];
}
int main() {
cin >> m >> n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> h[i][j];
}
}
// 初始化dp数组
memset(dp, -1, sizeof(dp));
int maxLen = 1;
// 从每个点开始搜索
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
maxLen = max(maxLen, dfs(i, j));
}
}
cout << maxLen << endl;
return 0;
}
通过此题,借助Claude的一句话:递归的本质是自相似性,即把一个大问题拆成具有相同结构的小问题,此题的dfs就是如此:与以往不同的是,此处的dfs不再仅是用于深度优先搜索的无意义量,此处的dfs就是代表从坐标(x,y)处出发的路径最大值。注:此处代码中的dp仅仅用来记忆结果,无动态规划的算法思维。

浙公网安备 33010602011771号