【洛谷P1343】[SHOI2002] 滑雪【DP 动态规划】

题目描述

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

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 24-17-16-11(从 24 开始,在 1 结束)。当然 25-24-23-…-3-2-1 更长。事实上,这是最长的一条。

输入格式

输入的第一行为表示区域的二维数组的行数 R 和列数 C。下面是 R 行,每行有C 个数,代表高度(两个数字之间用 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

分析&思路:

这道题是一个DP,从高度较低的点向高度较高的点推,再找到最大的点,输出它的值。但是动态规划必须是有序的,所以在这里我们要将这个二维的数组展开成一维的,进行排序后它就有序了。

CODE:

#include<iostream>
#include<algorithm> 
#include<cstdio>
using namespace std;
int n,m,g[10010],maxx;
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,1,-1};
struct node{
	int value;//值
	int x;//横座标
	int y;//纵座标
}f[10010];
bool cmp(node x,node y)
{
	return x.value<y.value;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&f[(i-1)*m+j].value);
			f[(i-1)*m+j].x=i;f[(i-1)*m+j].y=j;//预处理
		}
	sort(f+1,f+n*m+1,cmp);//排序
	//以下为DP部分
	for(int i=1;i<=n*m;i++)//枚举全部
		for(int j=i-1;j>0;j--)//从高到低
			for(int k=1;k<=4;k++)//四个方向
				if(f[i].x==f[j].x+dx[k]&&f[i].y==f[j].y+dy[k]&&f[i].value>f[j].value)//判断是否合法
				{
					g[i]=max(g[j]+1,g[i]);//动态转移
					if(g[i]>maxx)//取最大值
						maxx=g[i];
				}
	cout<<maxx+1;//因为本身也算一个节点
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章