![信息学奥赛一本通 1280:【例9.24】滑雪 | OpenJudge NOI 2.6 90:滑雪 | 洛谷 P1434 [SHOI2002] 滑雪,第1张 信息学奥赛一本通 1280:【例9.24】滑雪 | OpenJudge NOI 2.6 90:滑雪 | 洛谷 P1434 [SHOI2002] 滑雪,第1张](/aiimages/%E4%BF%A1%E6%81%AF%E5%AD%A6%E5%A5%A5%E8%B5%9B%E4%B8%80%E6%9C%AC%E9%80%9A+1280%EF%BC%9A%E3%80%90%E4%BE%8B9.24%E3%80%91%E6%BB%91%E9%9B%AA+%7C+OpenJudge+NOI+2.6+90%3A%E6%BB%91%E9%9B%AA+%7C+%E6%B4%9B%E8%B0%B7+P1434+%5BSHOI2002%5D+%E6%BB%91%E9%9B%AA.png)
ybt 1280:【例9.24】滑雪
OpenJudge NOI 2.6 90:滑雪
洛谷 P1434 [SHOI2002] 滑雪
集合:所有的路线
限制:从某位置出发的路线
属性:路线长度
条件:最长
统计量:路线长度
状态定义:dp[i][j]:从(i,j)出发的所有路线中,长度最长的路线的长度。
记第(i,j)位置的高度为a[i][j]。
集合:从(i,j)出发的所有路线
分割集合:根据下一步可以到达的位置分割集合。
下一步可以到达的位置有:(i-1,j), (i+1,j), (i,j-1), (i,j+1)。只要该位置的高度低于当前(i,j)位置的高度,就可以到达这里。
- 如果
a[i-1][j] < a[i][j],那么下一步可以到(i-1,j)。从(i,j)出发的最长路线长度,为从(i-1,j)出发的最长路线长度再加1,即dp[i][j] = dp[i-1][j] + 1。 - 如果
a[i+1][j] < a[i][j],那么下一步可以到(i+1,j)。从(i,j)出发的最长路线长度,为从(i+1,j)出发的最长路线长度再加1,即dp[i][j] = dp[i+1][j] + 1。 - 如果
a[i][j-1] < a[i][j],那么下一步可以到(i,j-1)。从(i,j)出发的最长路线长度,为从(i,j-1)出发的最长路线长度再加1,即dp[i][j] = dp[i][j-1] + 1。 - 如果
a[i][j+1] < a[i][j],那么下一步可以到(i,j+1)。从(i,j)出发的最长路线长度,为从(i,j+1)出发的最长路线长度再加1,即dp[i][j] = dp[i][j+1] + 1。 - 以上四种情况求最大值。
由于在求(i,j)时,其上下左右四个位置的状态:dp[i-1][j], dp[i+1][j], dp[i][j-1], dp[i][j+1]并不能确定都已经求出来了。因此可以通过记忆化递归的方法来求解状态。
设函数dfs(i, j),作用为求解状态dp[i][j]。如果dp[i][j]已经求出来了(值大于0),那么直接返回dp[i][j]。否则通过上述状态转移方程递归求解。
遍历所有的位置,求出从每个位置出发的路线的最长长度,求它们中的最大值,即为该问题的结果。
【题解代码】 解法1:动态规划 记忆化递归#include
using namespace std;
#define N 105
int dp[N][N], a[N][N], mx, r, c;//dp[i][j]:从(i,j)出发的最长路线的长度
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};//方向数组
int dfs(int sx, int sy)//求dp[sx][sy]
{
if(dp[sx][sy] > 0)//如果路径长度大于0,则已经求出过dp[sx][sy],直接返回该值。
return dp[sx][sy];
int route = 0;//从(sx,sy)周围位置出发能得到的最大路线数
for(int i = 0; i < 4; ++i)
{
int x = sx + dir[i][0], y = sy + dir[i][1];
if(x >= 1 && x <= r && y >= 1 && y <= c && a[x][y] > a[sx][sy])//如果
route = max(route, dfs(x, y));
}
return dp[sx][sy] = route+1;
}
int main()
{
cin >> r >> c;
for(int i = 1; i <= r; ++i)
for(int j = 1; j <= c; ++j)
cin >> a[i][j];
for(int i = 1; i <= r; ++i)
for(int j = 1; j <= c; ++j)
mx = max(mx, dfs(i, j));
cout << mx;
return 0;
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)