洛谷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;//完美撒花
初步发布时间:2019.11.25持续修改完善
原文地址:https://www.cnblogs.com/Dfkuaid-210/p/11929130.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法