今天酉时,不才蒟蒻正在洛谷的题海中迷茫的时候,找到了这样一道题:
但其实自己看并不难,不要被他的标签唬住了
题目描述
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 开始,在 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
提示/说明
对于 %100的数据,1≤R,C≤100。
他这个题目描述的属实难受看不懂
抽象一下,就一句话
求二维最长下降子序列
那就简单了
最长不下降子序列会吧?
就剩下一个二维了,也确实是这道题的难点
注意看,数据范围贼拉小
那不就直接暴力了吗
二维暴力是什么?
不就是深搜吗?
动态规划三要素:三要素没听过的或者不太懂的点我
初始化:memset
状态定义:dp[i][j]代表这个位置为起点的滑坡最多为多少
状态转移方程:一会儿再说
主函数:
scanf("%lld%lld",&r,&c);
for (int i=1;i<=r;i++){
for (int j=1;j<=c;j++){
scanf("%lld",&map[i][j]);
}
}
memset(dp,0,sizeof(dp));
for (int i=1;i<=r;i++){
for (int j=1;j<=c;j++){
dp[i][j]=dfs(i,j);
if (dp[i][j]>cnt){
cnt=dp[i][j];
}
}
}
printf("%lld",cnt);
那就下来就到重点的地方
dfs函数:
int dfs(int x,int y){
int now=1;
for(int i=0;i<4;i++){
int tx=x+dxy[i][0];
int ty=y+dxy[i][1];
if(tx>=1&&tx<=r&&ty>=1&&ty<=c&&map[x][y]>map[tx][ty]){
int temp=dfs(tx,ty)+1;
if(temp>now){
now=temp;
}
}
}
return now;
}
注意看for循环内部第四行
为什么要加一呢?
因为他滑坡下去,路程得算上起点吧?
提交上去
喜提TLE90分
主要的说明没问题了,接下来就是优化了
dp没什么可以优化的
那就优化dfs
要用到剪枝
加一个特判就行,如果dp[x][y]不为0,也就是说已经计算过了,那就直接返回
ac代码;
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
# define int long long
int r,c,cnt;
int map[105][105];
int dp[105][105];
int dxy[5][2]={{1,0},{-1,0},{0,1},{0,-1}};
int dfs(int x,int y){
if (dp[x][y]){
return dp[x][y];
}
int now=1;
for(int i=0;i<4;i++){
int tx=x+dxy[i][0];
int ty=y+dxy[i][1];
if(tx>=1&&tx<=r&&ty>=1&&ty<=c&&map[x][y]>map[tx][ty]){
int temp=dfs(tx,ty)+1;
if(temp>now){
now=temp;
}
}
}
return now;
}
signed main(){
scanf("%lld%lld",&r,&c);
for (int i=1;i<=r;i++){
for (int j=1;j<=c;j++){
scanf("%lld",&map[i][j]);
}
}
memset(dp,0,sizeof(dp));
for (int i=1;i<=r;i++){
for (int j=1;j<=c;j++){
dp[i][j]=dfs(i,j);
if (dp[i][j]>cnt){
cnt=dp[i][j];
}
}
}
printf("%lld",cnt);
return 0;
}
ac记录:
如果你觉得不才蒟蒻讲的不错,就点一个免费的赞吧