1. 程式人生 > 其它 >回溯法(含橋本分數式)

回溯法(含橋本分數式)

回溯很容易理解,其實就是一種稍微聰明一些的列舉方法。以我們常見的數字全排列為例子,我們就可以很輕鬆的理解它的思維方式,

給出3個數,然後得到它所有的排列組合:111、112、113、121、122、123、131等等。這樣的思路其實就是一種列舉,只是列舉某一位來得到全部的排列方式。基於這樣的思路,使用回溯法,新增一個條件,則可以得到不含重複數字的數字全排列。

給出程式碼,回溯法求數字全排列:

int a[10] = {}, b[10] = {};
	int n = 4;
	void hui(int step) {
		if (step > n) {
			for (int i = 1; i <= n; i++) {
				cout << a[i] << " ";
			}
			cout << endl;
		}
		for (int k = 1; k <= n; k++) {
			if (!b[k]) {
				a[step] = k;
				b[k] = 1;
				hui(step + 1);
				b[k] = 0;//回溯回來修改標誌防止影響取值
			}
		}	
	}

其實回溯法求全排列可以作為一個模板,只需要在輸出處新增條件,即可解題。下面以橋本分數算式為例。

橋本分數算式:

日本數學家橋本吉彥教授於1973年10月在我國山東舉行的中日美三國數學教育研討會上向與會者提出以下填數趣題:

把1,2, . . . 9這9個數填入下列算式的9個方格中(數字不得重複),使下列等式成立。並且注意a[1]<a[4]。

分析題意可以知道,此題可以使用全排列的方式求解。在輸出時檢驗其輸出結果是否滿足即可

        int a[10] = {}, b[10] = {};
	int n = 4;
	void hui(int step) {
		if (step > n) {
                        int m1 = a[2] * 10 + a[3];
			int m2 = a[5] * 10 + a[6];
			int m3 = a[8] * 10 + a[9];
			if (a[1] * m2 * m3 + a[4] * m1 * m3 == a[7] * m1 * m2&&a[1]<a[4]) {
                              for (int c = 1; c <= n; c++) {
                              cout << a[c] << " ";
                              }
                        cout << endl;
                        }//上面的if判斷即為對橋本分數式的檢驗程式
                }
		for (int k = 1; k <= n; k++) {
			if (!b[k]) {
				a[step] = k;
				b[k] = 1;
				hui(step + 1);
				b[k] = 0;//回溯回來修改標誌防止影響取值
			}
		}	
	}