題目描述
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;//因爲本身也算一個節點
}