2017-05-08 110 views
2

有任務計算矩陣中的房間面積。第一個輸入是行和列位置的座標 - 零點是自由空間,1是牆。問題是,填充函數給我堆棧溢出異常。洪水填充算法 - 房間面積

#include<iostream> 
#include<conio.h> 
using namespace std; 

int a[5][5] = { {0,0,1,0,0}, 
       {0,0,1,0,0}, 
       {0,0,1,1,1}, 
       {1,1,1,0,0}, 
       {0,0,1,0,0}, 
}; 

bool vis[5][5] = { {0,0,0,0,0}, 
        {0,0,0,0,0}, 
        {0,0,0,0,0}, 
        {0,0,0,0,0}, 
        {0,0,0,0,0}, 
}; 
int c = 0; 

void flood(int row, int col){ 
    if(row < 0 || row > 4 || col < 0 || col > 4) 
     return; 
    if(a[row][col] == 0 && !vis[row][col]){ 
     c++; 
     vis[row][col] = 1; 
    } 
    flood(row-1, col); 
    flood(row+1, col); 
    flood(row,col-1); 
    flood(row, col+1); 
} 

int main(){ 
    int row, column; 
    cin>>row>>column; 

    flood(row,column); 
    cout<< c; 

    getch(); 
return 0; 
} 

回答

2

如果您擊中了已經訪問的字段,則不應該遞歸。

在您的代碼中,這意味着擊中!vis[row][col]子句應阻止對flood的進一步遞歸調用。你可以簡單地通過在if內移動它們(或者更清楚一點,將所有東西移到外面並翻轉條件)來實現。這也可以防止當你碰到牆壁時發生遞歸,但這也是也是你想要什麼。

+0

我認爲,還應該注意的是,遞歸下降洪水填充算法通常是一個非常糟糕的想法:它總是傾向於填充整個區域中一個單一的,非常深的遞歸,所以如果'N'是圖像的寬度/高度,所需的堆棧空間是'O(N^2)'。當你移動到有趣的問題大小時,這會很快地發生段錯誤。 – cmaster

+0

@cmaster好點。即使是簡單的基於隊列的迭代方法也會更好。不過,這看起來像一個練習。 –

+0

遞歸深度問題是我們在實際需要使用填充填充時不可避免地遇到的一個問題。所以我猜,問題是讀者是否花了五分鐘才認識到存在一個根本性問題,或者花了半小時寫出一個遞歸洪泛加上不確定的時間來調試段錯誤,然後才得出遞歸洪水的結論填充是一個壞主意。從別人的經驗中學習比自己的錯誤更有效率。這就是爲什麼我通常喜歡對這些固有問題給予/接受警告。 – cmaster