回溯法與遞迴 C 中動態的二維陣列

2021-06-27 18:41:33 字數 2566 閱讀 3103

leetcode的題目,求出數獨遊戲的乙個解。

之前記得求解 全排列和八皇后問題也是用的回溯法。

分治法可以用遞迴是很顯然的,它們倆是天生一對;回溯法也可以。因為 試探求解子問題

下面**是我用遞迴回溯求解數獨的乙個解,6個測試用例,184ms,在c++分布段上處在中間,還行吧,以後有時間再研究。

關鍵是學到了一種方便地表示動態二維陣列的新方法。一維的動態陣列 就用new、vector、deque。二維的呢?

1、舊方法,比如:

int* baseaddr=new int[3*2]; // 3 行 2 列

typedef int int2 [2];

int2 * p=(int2 *)baseaddr;

for(int i=0;i<3;i++)

}delete baseaddr;

2、新方法,比如這道求解數獨的題目:

#include using namespace std;

void solvesudoku(vector> &board);

bool tillnow_boardisvalid_try_thisnumber( vector> & board, int i, int j, char c);

inline bool checkvalid( vector> & board, int i, int j, char c );

int main()

; vector> bd;

for(int i=0;i<9;i++)

bd.push_back(vector(sd[i],sd[i]+9));

solvesudoku(bd);

return 0;

}void solvesudoku(vector> &board)

for (char c='1';c<='9';c++)

}return;

} }

}bool tillnow_boardisvalid_try_thisnumber( vector> & board, int i, int j, char c)

if(ni==9)

for(;ni<9;ni++)

for (char cc='1';cc<='9';cc++)

}board[i][j]='.'; // the attempt ( board[i][j]=c ) has failed

return false;

} nj=0;

} return true;

}inline bool checkvalid( vector> & board, int i, int j, char c )

else if(board[i][k]==c)

} for(int k=0;k<9;k++)

else if(board[k][j]==c)

} int row=i/3*3;

int column=j/3*3;

for (int row=0;row<3;row++)

else if(board[row+row][column+column]==c)

} }return true;

}

第乙個關鍵 

寫遞迴程式,就是寫出遞推關係式的過程

,比如求斐波那契數fn:

f1=1,f2=1,f3=2,f4=3,f5=5,……fn=?

不想去求fn關於n的數學函式或者迭代過程:fn= φ(n) or fn=

而是得到 fn=f(n-1)+f(n-2)

這樣乙個自我指涉的式子,於是它就自動地運轉起來,不需要你用迴圈人為地推動它。把人腦從繁瑣的程式執行流程中解放了出來

遞迴不像迴圈,先不考慮其實現細節,先定義好 子問題,利用子問題的結果,設計求解原問題的演算法,即得到遞推關係式(把子問題看做已經完成的方案)。有的問題明顯蘊含著遞迴表示式,比如階乘在數學上的定義,子問題、遞推關係式都是顯然的。然而有的問題不這樣顯而易見,我們得自己定義 子問題,比如漢諾塔。基礎是分治法,把原問題分解為子問題(意味著問題的規模更小,n 更小),求解子問題,合併結果。回溯法的子問題就是試探求解。如何求解子問題呢?哈,「不用求」。因為遞迴就是要找 f( n ) 與 f (n-1) 的關係等式,不是求出f(n)=φ(n)。φ ()代表某一確定的,已知的過程,不像f()是未知的過程。

第二個關鍵 明確定義好 f(n) or f(n-1) 的功能介面,一丁點模糊的地方都不行。f(n-1) 執行前是什麼樣,執行中改變了什麼(執行後變成什麼樣),必須完全確定下來。不過往往不是一步到位的,要看「利用子問題的結果設計求解原問題的演算法」時的需求。定義

f(n-1) 的功能介面與利用f(n-1),設計求解f(n)的演算法兩者是相關的(因為f(n)  f(n-1) 要有相同的介面)。我一般按所問定義f(n-1) 的介面,利用它定義的f(n-1)所具有的功能,設計求解f(n)的演算法,即去實現f(n)的介面。然後你就知道子問題以及子問題的介面定義的合不合適。

二維陣列與遞迴

其實二維陣列其實就是每乙個元素為一維陣列的陣列。二維陣列格式1 資料型別 變數名 new 資料型別 m n m表示這個二維陣列有多少個一維陣列 必須寫上 n表示每乙個一維陣列的元素個數 可選 舉例 int arr newint 3 2 定義了乙個二維陣列arr,這個二維陣列有3個一維陣列,名稱為ar...

C 中的動態二維陣列

在c 中不能使用動態二維陣列。二維陣列本質就是陣列的陣列,陣列a row col 中,a row 就是陣列,按照這個想法,我們可以自己實現動態二維陣列。先給第一維分配記憶體空間,其內容為指向指標的指標,然後再給第二位分配記憶體。之前聽說過二維陣列是以行優先儲存或以列優先儲存,說明二維陣列記憶體中是連...

c 二維動態陣列

很多時候,我們無法得知或者不用去考慮程式在執行時需要建立多大的陣列,此時動態資料的建立就會顯得格外重要了,二維動態陣列具有很高的靈活性和實用性,廢話不多說,原始碼呈上!其中包括了一些vs記憶體檢測的語句,大家看注釋吧 include include using namespace std ifdef...