【洛谷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;//因爲本身也算一個節點
}

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