1. 程式人生 > 其它 >滑雪問題

滑雪問題

技術標籤:演算法學習記錄演算法

題目要求:
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; }