一道dfs和dp结合的好题 --- Longest Run on a SnowboardUVA-10285

时间:2023-03-08 21:20:06

题目链接:

https://vjudge.net/problem/19213/origin

大致题意:

一个滑雪者想知道自己在固定高度的山坡中最多能滑的距离是多少。

思路:

首先想到的就是dfs,但是。。超时了,所以我们要用到动态规划进行优化。

dfs的思路就是从第一个位置开始dfs搜索。

dp的思路就是数形的思维,每一个树的根节点就是dp[x][y]。这是一个4叉树,当dp[x1][y1] < dp[x][y]的时候进行向下递归,每次操作加上权值1,这个操作最终会返回一个最大值。

下面是AC代码:

#include <iostream>
#include <cstdio>
#include <string.h> using namespace std;
const int MX = +;
int vis[MX][MX]; //vis数组记忆化搜索,防止重复。但是在这道题貌似不需要。。。
int dp[MX][MX], mp[MX][MX];
int n, m, ans;
string name;
int xx[] = {, , -, };
int yy[] = {, , , -}; //四个方向 int dfs(int x, int y)
{
if(vis[x][y]) return dp[x][y];
for(int i = ; i < ; ++i)
{
int x1 = x+xx[i];
int y1 = y+yy[i];
if(x1 >= && x1 <= n && y1 >= && y1 <= m && mp[x1][y1] < mp[x][y]) //注意递归边界
{
dp[x][y] = max(dfs(x1, y1)+, dp[x][y]); //选权值最大的边
}
}
vis[x][y] = ; //记忆化搜索优化
return dp[x][y];
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
ans = ;
name.clear();
memset(vis, , sizeof(vis));
memset(dp, , sizeof(dp));
memset(mp, , sizeof(mp));
cin >> name;
scanf("%d %d", &n, &m); for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j)
scanf("%d", &mp[i][j]); //初始化mp数组 for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j)
{
int h = dfs(i, j);
ans = max(ans, h);
}
cout << name << ": " << ans+ << endl; //起始点也算
}
}

如有疑问,欢迎评论指出!