滑雪问题

滑雪问题(Vijos1011)
by mps

描述

顺治喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待太监们来载你。顺治想知道载一个区域中最长的滑坡。

区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

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更长。事实上,这是最长的一条。

格式

输入格式

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 500)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

输出格式

输出最长区域的长度。

样例1

样例输入1

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

样例输出1

25

限制

各个测试点2

思路

  我们发现题目中显然有最优子结构和重叠子问题性质,那么自然采用动态规划算法进行解决,那么,我们可以这么做:
  
/*
  阶段:地图上的任意一个位置
  状态:设f(i,j)表示(i,j)这个位置的最长路径
  决策:f(i,j)=max{f(i-1,j),f(i,j-1),f(i+1,j),f(i,j+1)}+1
  很明显有后效性,所以采用递归进行消除
*/ 
    这样就轻松的解决了此题

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <queue>
#include <deque>
using namespace std;


const int MaxN=1001;


/*
  阶段:地图上的任意一个位置
  状态:设f(i,j)表示(i,j)这个位置的最长路径
  决策:f(i,j)=max{f(i-1,j),f(i,j-1),f(i+1,j),f(i,j+1)}+1
  很明显有后效性,所以采用递归进行消除
*/ 
int f[MaxN][MaxN];
int a[MaxN][MaxN],n,m; 


void readfile(){
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
 for(j=1;j<=m;j++)
   scanf("%d",&a[i][j]);
memset(f,0,sizeof(f));
}

int dp(int x,int y){
if(f[x][y])return f[x][y];
int w;
if(x>1 && a[x-1][y]<a[x][y]){
w=dp(x-1,y);
if(w>f[x][y])f[x][y]=w;
}
if(y>1 && a[x][y-1]<a[x][y]){
w=dp(x,y-1);
if(w>f[x][y])f[x][y]=w;
}
if(x<n && a[x+1][y]<a[x][y]){
w=dp(x+1,y);
if(w>f[x][y])f[x][y]=w;
}
if(y<m && a[x][y+1]<a[x][y]){
w=dp(x,y+1);
if(w>f[x][y])f[x][y]=w;
}
return f[x][y]=f[x][y]+1;
}


void solve(){
  int ans=0;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      ans=max(ans,dp(i,j));
  printf("%d",ans);
}


int main(){
  readfile();
  solve();
  return 0;
}

这个算法的速度很快的,我们发现题目给了2s,而实际却1s都没有

评测结果

编译成功

测试数据 #0: Accepted, time = 109 ms, mem = 8348 KiB, score = 10

测试数据 #1: Accepted, time = 15 ms, mem = 8348 KiB, score = 10

测试数据 #2: Accepted, time = 31 ms, mem = 8348 KiB, score = 10

测试数据 #3: Accepted, time = 0 ms, mem = 8348 KiB, score = 10

测试数据 #4: Accepted, time = 62 ms, mem = 8352 KiB, score = 10

测试数据 #5: Accepted, time = 15 ms, mem = 8348 KiB, score = 10

测试数据 #6: Accepted, time = 15 ms, mem = 8352 KiB, score = 10

测试数据 #7: Accepted, time = 46 ms, mem = 8348 KiB, score = 10

测试数据 #8: Accepted, time = 15 ms, mem = 8348 KiB, score = 10

测试数据 #9: Accepted, time = 78 ms, mem = 8348 KiB, score = 10

Accepted, time = 386 ms, mem = 8352 KiB, score = 100


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值