找出最長的胖子

2021-07-05 11:26:58 字數 2296 閱讀 4045

題目:

有乙個boolean組成的矩陣,大小是n*m,代表路面,能不能在上面行走,假設胖子的形狀都是正方形,也就是s*s的矩陣,其中s代表胖子的邊長,現在想尋找從矩陣最左上角能走到矩陣最右下角的最大腰圍的胖子。而胖子只能往右邊和往下面兩個方向移動,且每次只能移動一步。要求每次胖子所占用的地面都是可以在上面行走的,也就是都是值為true的元素。

分析:

舉個栗子,有以下的矩陣,(其中綠色代表的是true,紅色代表的是false)

此圖中,最大的胖子的s可以達到2,按照如下圖中的路線行走,(藍色虛線代表最大的胖子,黃線代表走的路線)

所以應該返回2。

如果是乙個4*5的矩陣,並且裡面都是true,那麼應該返回4。

如果最小為1邊長的胖子也不能從左上角移動到右下角,那麼返回0。

怎麼思考這樣的問題,路徑的遍歷可以用dfs,那麼又如何找到最大的胖子的邊長呢?

一種比較暴力的方法就是遍歷從s = 1到min(n, m),然後對s的邊長進行dfs看是否能順利完成路徑,如果成功則記錄,如果失敗則停止,返回最後乙個成功的s就是最大的邊長。

但是這樣太費時了。

我的想法是:通過把問題分解成兩個子問題,通過遞迴去解決。

怎麼分解?題目中只能往右或者往下走。

舉個栗子,

如果往右走,它的最大的胖子的大小被兩個因素限制:第0列最大的連續true的數量mmax,以及子問題除去第0列剩下的矩陣的最大胖子rs

往右走的最大胖子right_s = min(mmax, rs)

如果往左走也是類似:

它的最大的胖子的大小被兩個因素限制:第0行最大的連續true的數量nmax,以及子問題除去第0列剩下的矩陣的最大胖子bs

往右走的最大胖子bottom_s = min(nmax, bs)

而最終的胖子的大小是s = max(right_s, bottom_s),即從往下走和往右走中選出最大值。

讓問題解函式為getmax(a, x, y, n, m),其中a表示矩陣,x,y表示胖子剛開始待的位置,n,m表示矩陣大小。

那麼問題分解的過程如下圖:

這是非常典型的分解問題+遞迴解決。

而終結的條件就是當胖子的右下角到達了n和m的邊界的時候,進行判斷是否胖子當前所佔的地方是否全為true,因為胖子來的路中左邊和右邊我們都通過最左列和最上行的true最大的數量判斷過,不過胖子最後佔的位置我們還沒有判斷,如果都為true,則當前胖子的長度s就是答案,否則s還要小。

**如下:

#include#include#include#include#includeusing namespace std;

int getmax(vector>&a, int x, int y, int n, int m)

}} }

if (flag == true)

int ret;

if (nmax == 0)

ret = min(mmax, getmax(a, x, y + 1, n, m));

else if (mmax == 0)

ret = min(nmax, getmax(a, x + 1, y, n, m));

else

ret = max(min(mmax, getmax(a, x + 1, y, n, m)), min(nmax, getmax(a, x, y + 1, n, m)));//子問題1和子問題2

return ret;

}int solution(vector> &a)

int main(), , , , };//答案是2

//vv = };//答案是1

//vv = , , , };//答案是0

//vv = , , };//答案是3

vv = , , };//答案是2

cout << solution(vv) << endl;

return 0;

}

——apie陳小旭

找出最長單詞

fcc裡的一道小演算法題 在句子中找出最長的單詞,並返回它的長度。函式的返回值應該是乙個數字。split 分解句子單詞,然後計算長度再比較就可以了。最開始是這樣寫的 function findlongestword str strarr.sort sortnum return strarr stra...

找出陣列中最長的平台

這個程式十分簡單,但是要編寫好卻不容易,因此在編寫程式時應該考慮下面幾點 使用的變數越少越好 能否只把陣列的元素每乙個都只查一次就得到結果?程式語句越少越好。實現如下 includeusing namespace std int main i遍歷的時候用 int i 1 h表示長度 初始化為0 in...

找出最長遞增子串行

例如給定乙個序列 1,5,2,4,8,3,7,11,17,5,20,11,其中最長遞增子串行為 1,2,4,8,11,17,20 求解思路 可以使用動態規劃解決此問題,用兩個陣列dp n 和pos n 其中dp用來表示到第i位時的最長子序列長度,而pos表示在這個最長子序列中上乙個元素的位置。這個演...