題目描述
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
一個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度會減小。在上面的例子中,一條可行的滑坡爲 2424-1717-1616-11(從 2424 開始,在 11 結束)。當然 2525-2424-2323-\ldots…-33-22-11 更長。事實上,這是最長的一條。
輸入格式
輸入的第一行爲表示區域的二維數組的行數 RR 和列數 CC。下面是 RR 行,每行有 CC 個數,代表高度(兩個數字之間用 11 個空格間隔)。
輸出格式
輸出區域中最長滑坡的長度。
輸入輸出樣例
輸入 #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
代碼題解
這個題百分之90完全是自己寫的,唯一有一個沒有通過,因爲超時了,參考了一下題解後改了就通過了。自己寫的那部分還是把我記憶化搜索的精髓,差點意思,後來重點標註了一下,關鍵地方要看dfs函數部分。
#include<iostream>
#include <algorithm>
using namespace std;
int r,c;
int a[1000][1000];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};//上下左右四個方向滑雪
int f[1000][1000];
int cnt=0;
//記憶化搜索的方式
//什麼是記憶化搜索? 就是說之前已經搜索過的值把他記錄下來,這樣就可以直接用了,不用重複搜索
int dfs(int x,int y){
if(f[x][y]) return f[x][y];//這裏檢查一下是不是之前在搜索的時候已經有數值了,有就直接返回不用再搜
for(int i=0;i<=3;i++)
{
if(a[x][y]>a[x+dx[i]][y+dy[i]]&& x+dx[i]>=1 && x+dx[i]<=r && y+dy[i]>=1&& y+dy[i]<=c)
{
dfs(x+dx[i],y+dy[i]);
f[x][y]=max(f[x][y],f[x+dx[i]][y+dy[i]]+1);
//對於當前這個點來說,有四個方向可供選擇,要選擇其中最佳的路徑,所以有這個狀態轉移方程
}
}
return f[x][y];
}
int main(){
cin>>r>>c;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
cin>>a[i][j];
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
cnt=max(cnt,dfs(i,j));
cout<<cnt+1;//結果爲啥要加1,因爲哪怕只有一個點也是有值的爲1,而前面初始化f[][]的時候值爲0,所以最後要加上
return 0;
}