[SHOI2002]滑雪-题解报告

题目描述

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

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-\ldots…-33-22-11 更长。事实上,这是最长的一条。


本题关键字:记忆化搜索。

首先,这题为什么会想到记忆化?(知道的人直接跳过)

在dfs每种情况是,可能这个点之前已经搜过了,没必要再去搜索了,因此不如存储记住,就没必要再去dfs了。



本题的主要思路:

1.先去想dfs怎么做:

这题每个点出发有可能,所以我们每个点都要开始dfs,最后取他们的最大值。

dfs部分和类似的迷宫差不多,用两个数组表示4个方向:

dx[4]={0,0,1,-1};
dy[4]={1,-1,0,0};

改变方向直接xx=x+dx[i] , yy=y+dy[i]

接下来判断这个方向是否在地图范围内,即

if(xx>0&&xx<=R&&yy>0&&yy<=C)

当然还要判断这个点是否能滑到,也就是高度要前一个低:

if(a[xx][yy]<a[x][y])//a为高度

很明显,因为低的不可能滑向高的,所以我们不需要再开一个数组去记录这个点是否走过。

接下来,就要往四个方向搜索,取四个方向中距离最长的,然后+1,这就是这个点的结果了。

2.记忆化搜索怎么写

很显然,直接dfs会TLE。那么就需要记忆化来优化。

用s[i][j]表示从(i,j)点出发能走的最长距离。

每次搜索一次记忆一次即可。

下面给刚接触不怎么明白的人举例:(已经理解的人跳过)

由于样例不好讲我自己举例子:

3 3
1 1 3
2 3 4
1 1 1

先去找(1,1)的最长距离,很明显为1

接着找(1,2)的最长距离,很明显为1

接着找(1,3)的最长距离,为2((1,3)->(1,2))

然后找(2,1)的最长距离,为2((2,1)->(1,1))

然后是(2,2)的最长距离,如果没有记忆化,那么搜索过程为:(2,2)->(2,1)->(1,1)

但是(2,1)之前已经搜过了,再去搜就是浪费时间,之前搜索已经知道(2,1)的值为2,那么搜索过程就是缩短为:(2,2)->(2,1),即为3



下面附上我的代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,m,a[201][201],s[201][201],ans;
bool use[201][201];//这个就是所谓的不需要
int dfs(int x,int y){
    if(s[x][y])return s[x][y];//记忆化搜索
    s[x][y]=1;//题目中答案是有包含这个点的
    for(int i=0;i<4;i++)
    {  int xx=dx[i]+x;
       int yy=dy[i]+y;//四个方向
       if(xx>0&&yy>0&&xx<=n&&yy<=m&&a[x][y]>a[xx][yy]){
          dfs(xx,yy);
          s[x][y]=max(s[x][y],s[xx][yy]+1);
       }
    }
    return s[x][y];
}
int main()
{
   scanf("%d%d",&n,&m);//同题目的R,C
   for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
       scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)//找从每个出发的最长距离
      for(int j=1;j<=m;j++)
        ans=max(ans,dfs(i,j));//取最大值
    printf("%d",ans);
    return 0;
}
// by Rainy7

原文地址:https://www.cnblogs.com/Rainy7/p/SHOI2002-skiing.html

时间: 2024-11-17 03:08:48

[SHOI2002]滑雪-题解报告的相关文章

cojs 强连通图计数1-2 题解报告

OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一改就可以了 首先我们考虑不合法的方案强连通分量缩点后一定是DAG 考虑子问题:DAG计数 做法可以参考<cojs DAG计数1-4 题解报告> 这里给出转移方程 f(n)=sigma((-1)^(k-1)*C(n,k)*2^(k*(n-k))*f(n-k)) 如果考虑上强连通分量缩点的情况呢? 我

2016 年宁波工程学院第七届ACM校赛题解报告

2016 年宁波工程学院第七届ACM校赛题解报告 本题解代码直接为比赛代码,仅供参考. A,B,C,D,G,H,J,K,L,M 来自 Ticsmtc 同学. F 来自 Gealo 同学. E,I 来自Alex 学长. Promblem A :    Two Sum 时间限制: 1 Sec  内存限制: 64 MB 题目描述: 给出n个数,另外给出?个整数S,判断是否可以从中取出2个数,使得这两个数的和是S. 输入: 第?行有个整数T(1 <= T <= 10),代表数据组数. 对于每组数据,第

Code[VS] 2152 滑雪题解

Code[VS] 2152 滑雪题解 题目描述 Description trs喜欢滑雪.他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形.为了得到更快的速度,滑行的路线必须向下倾斜.例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一.例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条. 输入描述 Input Description 输入文件 第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列.第

线段树&#183;题解报告

线段树·题解报告 参考资料 ·课件 线段树 --刘汝佳 统计的力量,线段树全接触 --张昆玮 ·Blog [完全版]线段树 从普通线段树到zkw线段树 [总结][数据结构]ZKW线段树详解 选题目录 · Hdu1166 敌兵布阵(单点更新,区间求和) · Hdu1754 I Hate It(单点更新,RMQ) · Hdu3308 LCIS(单点更新,区间并) · Poj3468 A Simple Problem with Integers(区间加减,区间求和) · Poj2777 Count C

题解报告:hdu 1162 Eddy&#39;s picture

Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to become a painter.Every day Eddy draws pictures in his small room, and he usually puts out his newest pictures to let his friends appreciate. but the result i

题解报告:poj 3320 Jessica&#39;s Reading Problem(尺取法)

Description Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The final exam is coming, yet she has spent little time on it. If she wants to pass it, she has to master all ideas included in a very thick text book. The au

题解报告:poj 2480 Longge&#39;s problem(欧拉函数)

Description Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N. 

题解报告(CDUT暑期集训——第三场)

题解报告(CDUT暑期集训--第三场) A - Problem A. Ascending Rating HDU - 6319 思路:单调队列板子题?(但是弱的一批的我还是不会用(有空补上 用的滑动窗口算法 按着题解的从后往前做(ps:菜是原罪 AC代码 #include<stdio.h> #include<iostream> #include<math.h> #include<algorithm> #include<string.h> #incl

CFEducational Codeforces Round 66题解报告

CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第\(k\)小的值 那么问题就变成了 每一个数变成了\([x-mid,x+mid]\)的一段区间,如果有一个位置被覆盖了超过\(k\)次 那么\(mid\)一定合法 类似括号匹配 每次碰到左端点就贡献+1 右端点就统计答案然后-1 维护答案的同时顺便维护位置就好了 #include<cstdio>