滑雪問題
阿新 • • 發佈:2020-12-14
題目要求:
Michael 喜歡滑雪。為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,不得不再次走上坡或者等付升降機來載你。Michael 想知道在一個區域中最長的滑坡。
區域由一個二維陣列給出。陣列的每個數字代表點的高度。
當且僅當高度減小,一個人可以從某個點滑向上下左右相鄰四個點之一。
請設計演算法求解以上問題並做分析
主要思路:
因為本題要求最長的滑雪坡的長度,即求一個最長的下降序列,並且只能向上下左右走,並且只能走更低的位置,這樣的話,可以用遞迴DFS搜尋每一個點能夠下降的最長的長度,這裡我定義了一個4x2的陣列,來表示當前數的上下左右四個方向,分別與當前數進行對比,只有當方向上的數比當前數小,才能下滑,這樣搜尋直到搜到邊界返回(邊界就是上下左右都不能走,然後自己的值是 1 ),但是這樣搜尋會花費很多時間,因為進行了太多的重複搜尋。所以可以用一個數組maxLen,先對它進行初始化,便於以後判斷當前點是否搜尋過,然後儲存搜尋過的最大值,就可以避免重複搜尋,每當再搜尋到這裡時,直接用它已經搜尋過的值即可。具體過程在程式碼註釋中解釋說明。
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int to[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};//用來表示向右、左、上、下四個方向滑
int n, m;
int high[105][105]; //存放各點的高度
int maxLen[105][105]; //存放各點的搜尋記錄
bool check(int x, int y)//判斷該點是否還在區域內
{
if(x >= 1 && y >= 1 && x <= n && y <= m)
return 1;
else
return 0;
}
int max(int x, int y)
{
if (x > y)
{
return x;
}
else
{
return y;
}
}
int dfs(int x, int y)
{
if (maxLen[x][y]!= 0) //退出邊界 ,這個點已經搜尋過,或者這個點是邊界
return maxLen[x][y];
maxLen[x][y] = 1; //最低的點就是1;
for(int i = 0; i <= 4; i++)//分別搜尋右、左、上、下四個方向的高度與當前的進行對比
{
int x1 = x + to[i][0];
int y1 = y + to[i][1];
if( check(x1, y1) && high[x1][y1] < high[x][y])//判斷能否向下滑
{
maxLen[x][y] = max(dfs(x1, y1) + 1, maxLen[x][y]);//下滑後繼續判斷
}
}
return maxLen[x][y]; //返回搜尋過的點,並儲存在陣列中
}
int main()
{
int ans = 1;
cout<<"請輸入表示區域的行數和列數:";
cin>>n>>m;
cout<<"請按行輸入各處的高度值:";
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin >> high[i][j];
maxLen[i][j] = 0; //先對記錄陣列進行初始化
}
}
for(int s = 1; s <= n; s++)
{
for(int t = 1; t <= m; t++)
{
ans = max(ans, dfs(s, t)); //搜尋每一個點,並且找出最大值,並且不斷更新這個最大值
}
}
cout<<"該區域中的最長滑坡為"<<ans<<"米。"<<endl;
return 0;
}