POJ088滑雪(记忆化搜索|动态规划)
2016-01-03 22:58
204 查看
滑雪
Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
Sample Output
25
思路分析:
这个问题应该来说是个简单的,很容易想到用动态规划去做的题目。这个问题满足最有子结构
是比较容易看出来。非常容易建立如下递归式:
如果从i,j可以顺着某侧滑的话:
dp[i][j] = max{dp[i-1][j],dp[i][j-1],dp[i+1][j],dp[i][j+1]}+1
那么我们很容易写出递归的:
int dfs(int i,int j){
for(i,j上侧,下侧,左侧,右侧)
if(该位置没有越界){
if(顺着该侧可以往下滑)
如果该侧位置可以滑行的距离(递归调用dis函数)大于dp[i][j],则把dp[i][j]改成该距离+1
}
}
把这个递归改成动态规划很容易,只要在开始判断一下
if(dp[i][j]) return dp[i][j]; //dp[i][j]开始为0
这样基本上就可以很顺畅的写出代码了
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 86673 | Accepted: 32434 |
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
Sample Output
25
思路分析:
这个问题应该来说是个简单的,很容易想到用动态规划去做的题目。这个问题满足最有子结构
是比较容易看出来。非常容易建立如下递归式:
如果从i,j可以顺着某侧滑的话:
dp[i][j] = max{dp[i-1][j],dp[i][j-1],dp[i+1][j],dp[i][j+1]}+1
那么我们很容易写出递归的:
int dfs(int i,int j){
for(i,j上侧,下侧,左侧,右侧)
if(该位置没有越界){
if(顺着该侧可以往下滑)
如果该侧位置可以滑行的距离(递归调用dis函数)大于dp[i][j],则把dp[i][j]改成该距离+1
}
}
把这个递归改成动态规划很容易,只要在开始判断一下
if(dp[i][j]) return dp[i][j]; //dp[i][j]开始为0
这样基本上就可以很顺畅的写出代码了
/********************************************************************* > File Name: A - Number Sequence.cpp > Author: Tailless > Mail: xihuanjin1@gmail.com ********************************************************************/ #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <cstdlib> #include <iomanip> #include <vector> #include <ctime> #include <cmath> #include <stack> #include <queue> #include <list> #include <map> #include <set> #define C 0.57721566490153286060651209 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long LL; const int INF=0x3f3f3f3f; const double eps=1e-10; const double PI=acos(-1.0); const int maxn=1000009; const int maxm=1000009; int h[101][101]; //输入的高度值 int dp[101][101];//记录了每个点可以滑行的最大距离 int dx[]={-1,1,0,0};//为了方便上下左右侧的滑行的最大距离而使用的方便数组 int dy[]={0,0,-1,1}; int r,c;//输入的行和列 bool check_in(int i,int j) { return i >= 0 && i < r && j >= 0 && j < c; } int dfs(int i,int j) { int temp; if(dp[i][j])//如果已经求出来了,直接返回 return dp[i][j]; for(int k=0;k<4;k++) { if(check_in(i+dx[k],j+dy[k]))//如果没有越界 { if(h[i][j]>h[i+dx[k]][j+dy[k]])//如果顺着该侧可以滑 { temp = dfs(i+dx[k],j+dy[k]);//递归求dis(i+dx[k],j+dy[k]),并保存在临时变量temp中 dp[i][j]=dp[i][j]>temp ? dp[i][j] : temp + 1;//如果dp[i][j]比temp小,则取temp+1 } } } return dp[i][j]; } int main() { int max_dis=0; int temp; int i,j; cin>> r>>c; for(i=0;i<r;i++) { for(j=0;j<c;j++) { cin>>h[i][j]; dp[i][j] = 0; } } for(i=0;i<r;i++) { for(j=0;j<c;j++) { temp=dfs(i,j); max_dis=max_dis > temp ? max_dis : temp; } } cout<<max_dis+1<<endl; return 0; }
相关文章推荐
- VS2010 VS2012拖拽NumericUpDown控件直接卡死的解决办法
- 09Java语法回顾map集合
- 电信联通合并传闻:解读未来通信行业发展趋向
- 孢子框架-互联网金融平台微服务架构设计
- 惯性导航之Runge-Kunta法更新四元数(六)
- 机器学习入门系列二(关键词:多变量(非)线性回归,批处理,特征缩放,正规方程)
- 这是我参加51CTO软考薛大龙老师班的心得体会!
- iOS之实现倒计时功能
- (转)Linux概念架构的理解
- 罗永浩 2015跨年演讲《时间的朋友》
- linux下命令执行时间统计工具time使用小结
- 2015年终总结
- oracle的主键
- NYOJ88汉诺塔(一)(快速幂&同余定理)
- (二)黑马程序员——面向对象
- 类集框架笔记2
- VFS分析(二)基本数据结构(持续更新)
- Sublime
- Java集合与数组实现升序排序的算法设计
- android 控件响应的各种方法