洛谷P1434滑雪讲解

时间:2019-11-25
本文章向大家介绍洛谷P1434滑雪讲解,主要包括洛谷P1434滑雪讲解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题源:【是兄弟就来砍我】


我觉得这道题主要方法应该有两种:

  • 动态规划
  •  搜索

下面会分别对这两种方法进行简述



 一,动态规划法
首先的想法是用L(i,j)表示从点(i,j)出发能到达的最长距离。因为从(i,j)出发最少能滑行自己1格,所以每个点L值都先初始化为1

我们可以从 (i,j) 出发,向四周寻找,如果四周没有比他低的点,那么L(i,j)即为1,否则L(i,j)就为从(i,j)出发四周高度比L低且L值最大的那个点P的L值加1
递推时的顺序为点的高度由低到高,那么在递推过程中,计算L(i,j)时,他四周比他低的点P的L值一定已经被计算出来了
接下来需要解决的问题便是如何按点的高度由小到大递推

关于这个问题,我们难道要每次递推时用两遍循环找出当前未递推的最低点?

显然不可取,时间复杂度会爆炸的。那么就考虑能否一个sort()解决问题懒得自己写排序)。sort()能给一个二维数组排序?不知大佬们怎么想,反正本蒟蒻不会。。。那为了`sort()更香可以方便的使用,我用一个一维数组进行存储每个点的数据。

这时候不得不说,结构体真香真的实用。下面用代码直观地说一下这个结构体

1 struct Point{
2 int r; //行号
3 int c; //列号
4 int h; //高度
5 bool operator < (const Point & p) const {
6 return h < p.h;
7 }//构造函数,不懂的同学可以写一个cmp代替,下面代码会有特别说明
8 };Point point[10101];


为了方便储存以及不造成浪费个人习惯)这里i和j都从0开始取,那么点(i,j)用point数组存的下标为c * i + j
 由于i,j从0开始存,c * i + j这个式子表示的是第i+1行第j+1个数,那么,i最大为R-1,j最大为C-1,整个数组最大下标为C*(R-1)+C-1,即C*R-1
 若i,j从1开始取,为保证运算方便及善待空间,下标应为C*(i-1)+j-1

该算法的分析已给出,大家可以结合代码自行理解

 1 #include <iostream>//头文件,不多解释
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 struct Point{
 6     int r;//行号
 7     int c;//列号
 8     int h;//高度
 9     bool operator < (const Point & p) const {
10         return h < p.h;//构造函数,不会的可删掉看下面cmp
11     }
12 };Point point[10101];
13 int cmp(Point a,Point b){
14     if (a.h < b.h)   //如果a的高度小于b的高度
15       return 1;//返回真
16     else
17       return 0;//否则返回假
18 }
19 int R,C,ans = -0x3ffff;//需初始化ans为较小值(害怕玄学出错)
20 int a[101][101],d[102][102];//a为每点的高度,d为该点可滑行的最大值
21 int main(){
22     cin >> R >> C;
23     for (int i = 0;i < R;i ++)
24       for (int j = 0;j < C;j ++){
25           cin >> a[i][j];//输入点的高度
26           point[i * C + j].h = a[i][j];//根据上面所说的下标,
27           point[i * C + j].r = i;          //对点的数据进行存储
28           point[i * C + j].c = j;
29           d[i][j] = 1;            //初始可滑行长度为1
30       }
31     sort(point,point + R * C);//如果用了cmp可换为sort(point,point + R * C,cmp);
32     for (int i = 0;i < R * C;i ++){
33         int r = point[i].r;//找一个替身,怕玄学或运算时出错
34         int c = point[i].c;//同理
35         if (r > 0 && a[r - 1][c] < a[r][c])//找上面的
36           d[r][c] = max(d[r][c],d[r - 1][c] + 1);//进行更新
37         if (c > 0 && a[r][c - 1] < a[r][c])//找左面的
38           d[r][c] = max(d[r][c],d[r][c - 1] + 1);//进行更新
39         if (r < R - 1 && a[r + 1][c] < a[r][c])//找下面的
40           d[r][c] = max(d[r][c],d[r + 1][c] + 1);//进行更新
41         if (c < C - 1 && a[r][c + 1] < a[r][c])//找右面的
42           d[r][c] = max(d[r][c],d[r][c + 1] + 1); //进行更新
43     }
44     for (int i = 0;i < R;i ++)
45       for (int j = 0;j < C;j ++)
46         ans = max(ans,d[i][j]); //找出最大值
47     cout << ans;
48     return 0;//完美撒花
View Code

初步发布时间:2019.11.25持续修改完善

原文地址:https://www.cnblogs.com/Dfkuaid-210/p/11929130.html