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...