acwing 901. 滑雪

题目描述

给定一个 R 行 C 列的矩阵,表示一个矩形网格滑雪场。

矩阵中第 i 行第 j 列的点表示滑雪场的第 i 行第 j 列区域的高度。

一个人从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。

当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。

下面给出一个矩阵作为例子:

 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−2−1。

在给定矩阵中,最长的滑行轨迹为 25−24−23−…−3−2−1,沿途共经过 25 个区域。

现在给定你一个二维矩阵表示滑雪场各区域的高度,请你找出在该滑雪场中能够完成的最长滑雪轨迹,并输出其长度(可经过最大区域数)。

输入格式

第一行包含两个整数 R 和C。

接下来 R 行,每行包含 C 个整数,表示完整的二维矩阵。

输出格式

输出一个整数,表示可完成的最长滑雪长度。

数据范围

1≤R,C≤300
0≤矩阵中整数≤10000

输入样例:

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

输出样例:

25

动态规划算法求解

分析

首先记录每个点的坐标和数值,然后从大到小排序,然后依次遍历每个点,根据该点上下左右值大小的情况,如果四个方向存在比该点数值大的,那么就可以对该点的距离更新

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

typedef pair<int, pair<int,int>> Point;

const int N = 310;
int g[N][N]; // 地图
int d[N][N]; // 到该点的最长距离


vector<Point>  points;

int n, m;

bool cmp(Point a, Point b)
{
	return a.first > b.first;
}
 
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < m; j++)
		{
			scanf("%d", &g[i][j]);
			d[i][j] = 1; //
			 
			Point t;
			t.first = g[i][j], t.second.first = i, t.second.second = j;
			
			points.push_back(t);
		}
	}
	sort(points.begin(), points.end(), cmp);

	int res = 1;
	// 上下左右 
	int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; 
	for(auto p : points)
	{
		int val = p.first, x = p.second.first, y = p.second.second;
		// 对上下左右四个方向更新
		for(int i = 0; i < 4; i++)
		{
			int nx = x + dx[i], ny = y + dy[i];
			if(nx >= 0 && nx < n && ny >= 0 && ny < m && g[nx][ny] < g[x][y])
			{
				d[nx][ny] = max(d[nx][ny], d[x][y] + 1);
			}
			res = max(res, d[nx][ny]);
		}
	}
	
	cout << res << endl;

	return 0;

} 

时间复杂度

参考文章

posted @ 2022-02-26 16:37  VanHope  阅读(36)  评论(0编辑  收藏  举报