Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。 M i c h a e l 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
−
1
24−17−16−1
24−17−16−1
24
−
17
−
16
−
1
24−17−16−1
24−17−16−1。当然
25
−
24
−
23
−
.
.
.
−
3
−
2
−
1
25−24−23−...−3−2−1
25−24−23−...−3−2−1
25 − 24 − 23 − . . . − 3 − 2 − 1 25−24−23−...−3−2−1 25−24−23−...−3−2−1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数
R
R
R
R
R
R和列数
C
(
1
<
=
R
,
C
<
=
100
)
C
(
1
<
=
R
,
C
<
=
100
)
C(1<=R,C<=100)C(1<=R,C<=100)
C(1<=R,C<=100)C(1<=R,C<=100)。下面是
R
R
R行,每行有
C
C
C个整数,代表高度
h
h
,
0
<
=
h
<
=
10000
hh,0<=h<=10000
hh,0<=h<=10000
0 < = h < = 10000 0<=h<=10000 0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
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
Sample Output
25
解题思路
- 记忆化搜索:
-
D
P
:
DP :
DP: 因为必须从低到高,所以可以记录每个点的位置,然后排序矩阵。每个点扩展四个点,如果可以到达,那么更新四个方向。
f [ x + w x [ i ] ] [ y + w y [ i ] ] = m a x ( f [ x + w x [ i ] ] [ y + w y [ i ] ] , f [ x ] [ y ] + 1 ) f[x+wx[i]][y+wy[i]]=max(f[x+wx[i]][y+wy[i]],f[x][y]+1) f[x+wx[i]][y+wy[i]]=max(f[x+wx[i]][y+wy[i]],f[x][y]+1)
代码
DP:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int r,c;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
int p[500][500],p1[500][500]={1};
int k=0;
struct s{
int a,b,c;
}bsy[100010];
bool cmp(const s&k,const s&l)
{
return k.a<l.a;
}
void dp(){
for(int i=1;i<=k;i++){
for(int j=1;j<=4;j++)
{
if(bsy[i].b+dx[j]<=r&&bsy[i].b+dx[j]>0&&bsy[i].c+dy[j]>0&&bsy[i].c+dy[j]<=c)//如果可以到达
{
if(p[bsy[i].b+dx[j]][bsy[i].c+dy[j]]<p[bsy[i].b][bsy[i].c])
p1[bsy[i].b][bsy[i].c]=max(p1[bsy[i].b][bsy[i].c],p1[bsy[i].b+dx[j]][bsy[i].c+dy[j]]+1);//更新
}
}
}
}
int main(){
cin>>r>>c;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
cin>>p[i][j];
k++;
bsy[k].a=p[i][j];
bsy[k].b=i;
bsy[k].c=j;//记录位置
}
}
sort(bsy+1,bsy+k+1,cmp);//排序
dp();
int ans=-1000000000;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
ans=max(ans,p1[i][j]);
}
cout<<ans+1;
}
记忆化搜索:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int r,c;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
int p[500][500],bsy[510][510];
int dfs(int x,int y)
{
if(p[x][y])
return p[x][y];//如果这个点找过了,就直接返回
for(int i=1;i<=4;i++)
{
if(x+dx[i]<=r&&x+dx[i]>0&&y+dy[i]<=c&&y+dy[i]>0&&bsy[x+dx[i]][y+dy[i]]<bsy[x][y])
{
p[x][y]=max(p[x][y],dfs(x+dx[i],y+dy[i])+1);//更新最大值
}
}
if(!p[x][y])//如果四个方向都不行,赋1
p[x][y]=1;
return p[x][y];
}
int main(){
cin>>r>>c;
int n,ans=-1000000000;
int k=0;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
cin>>bsy[i][j];
}
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
ans=max(ans,dfs(i,j));
}
cout<<ans;
}