用“动态规划”解决最长滑雪道问题
2014-09-15 16:00
204 查看
转自:http://qu66q.iteye.com/blog/2072272
题目大意:
给你一个矩阵,当做滑雪场,矩阵的每个单元中的数代表高度,滑雪者只能从高的滑到低的地方,且方向只能是上,下,左和右,问滑雪者最长能滑几个单元?
解题思路:
该题本质上就是求矩阵上的最长严格连续递减(或递增)序列,即序列中的元素不能相等,而且前后之间必须相邻。该题属于动态规划问题,要用到递归。
已找递减序列为例,设dp[i][j]表示第i,j点所构成的序列有多长,求这个值,只需要对其上,下,左和右四个方向进行比较就可以,设board表示题目给的矩阵,dfs( i , j )表示求第i,j个点构成的序列长度,则可以得到
若board[i][j] > board[i-1][j], 则dp[i][j] = dp[i-1][j] + 1, 而dp[i-1][j]可以用递归求出,则状态转移方程为:
dp[i][j] = dfs( i-1 , j ) + 1;
但是还不够,要对board[i][j]四个方向都计算一遍,取最大的,所以使用
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
然后进行一次循环,取出最大的值赋给dp[i][j],所以最终的状态转移方程为:
temp = max( temp, dfs( i + dx[k], j + dy[k] ) + 1 );
代码:
Cpp代码
![](http://qu66q.iteye.com/images/icon_star.png)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int dp[105][105], board[105][105];
int dfs( int i, int j );
int main()
{
freopen( "test.txt", "r", stdin );
int T, m, n;
char name[50];
cin>>T;
while( T-- )
{
memset( dp, -1, sizeof( dp ) );
memset( board, 1, sizeof( board ) );
cin>>name>>m>>n;
for( int i = 1; i <= m; i++ )
{
for( int j = 1; j <= n; j++ )
{
cin>>board[i][j];
}
}
int ans = 0;
for( int i = 1; i <= m; i++ )
{
for( int j = 1; j <= n; j++ )
{
ans = max( ans, dfs( i, j ) );
}
}
cout<<name<<": "<<ans<<endl;
}
return 0;
}
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
int dfs( int i, int j )
{
if( dp[i][j] >= 0 )
return dp[i][j];
int temp = 1;
for( int k = 0; k < 4; k++ )
{
if( board[i + dx[k]][j + dy[k]] < board[i][j] )
temp = max( temp, dfs( i + dx[k], j + dy[k] ) + 1 );
}
return (dp[i][j] = temp);
}
题目大意:
给你一个矩阵,当做滑雪场,矩阵的每个单元中的数代表高度,滑雪者只能从高的滑到低的地方,且方向只能是上,下,左和右,问滑雪者最长能滑几个单元?
解题思路:
该题本质上就是求矩阵上的最长严格连续递减(或递增)序列,即序列中的元素不能相等,而且前后之间必须相邻。该题属于动态规划问题,要用到递归。
已找递减序列为例,设dp[i][j]表示第i,j点所构成的序列有多长,求这个值,只需要对其上,下,左和右四个方向进行比较就可以,设board表示题目给的矩阵,dfs( i , j )表示求第i,j个点构成的序列长度,则可以得到
若board[i][j] > board[i-1][j], 则dp[i][j] = dp[i-1][j] + 1, 而dp[i-1][j]可以用递归求出,则状态转移方程为:
dp[i][j] = dfs( i-1 , j ) + 1;
但是还不够,要对board[i][j]四个方向都计算一遍,取最大的,所以使用
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
然后进行一次循环,取出最大的值赋给dp[i][j],所以最终的状态转移方程为:
temp = max( temp, dfs( i + dx[k], j + dy[k] ) + 1 );
代码:
Cpp代码
![](http://qu66q.iteye.com/images/icon_star.png)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int dp[105][105], board[105][105];
int dfs( int i, int j );
int main()
{
freopen( "test.txt", "r", stdin );
int T, m, n;
char name[50];
cin>>T;
while( T-- )
{
memset( dp, -1, sizeof( dp ) );
memset( board, 1, sizeof( board ) );
cin>>name>>m>>n;
for( int i = 1; i <= m; i++ )
{
for( int j = 1; j <= n; j++ )
{
cin>>board[i][j];
}
}
int ans = 0;
for( int i = 1; i <= m; i++ )
{
for( int j = 1; j <= n; j++ )
{
ans = max( ans, dfs( i, j ) );
}
}
cout<<name<<": "<<ans<<endl;
}
return 0;
}
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
int dfs( int i, int j )
{
if( dp[i][j] >= 0 )
return dp[i][j];
int temp = 1;
for( int k = 0; k < 4; k++ )
{
if( board[i + dx[k]][j + dy[k]] < board[i][j] )
temp = max( temp, dfs( i + dx[k], j + dy[k] ) + 1 );
}
return (dp[i][j] = temp);
}
相关文章推荐
- 用“动态规划”解决最长滑雪道问题
- PKU 1050 动态规划-解决最大子矩阵问题
- 算法设计与分析3 - 动态规划解决四柱汉诺塔问题 推荐
- 动态规划解决问题的一般思路
- 数据结构(C#)--利用动态规划解决0-1背包问题
- 最长上升子序列问题(动态规划)
- 动态规划求解最长公共子串问题
- 动态规划解决01背包问题
- 算法回顾 - 动态规划 之 最长公共子串问题
- 动态规划解决跳台阶问题
- 动态规划解决最大子矩阵问题
- AC解 - 用动态规划解决一道排列组合计数问题(序关系计算)
- POJ 1088 滑雪问题 动态规划
- 动态规划解决背包问题
- 使用动态规划解决有关数字组合的问题
- 使用动态规划解决有关数字组合的问题
- 动态规划之最长递增子序列问题
- 动态规划解决矩阵连乘问题
- 动态规划解决跳台阶问题
- poj 百练1088滑雪路线问题 动态规划