Fork me on GitHub

回溯法(含桥本分数式)

回溯很容易理解,其实就是一种稍微聪明一些的枚举方法。以我们常见的数字全排列为例子,我们就可以很轻松的理解它的思维方式,

给出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]。

image-20211101155239943

分析题意可以知道,此题可以使用全排列的方式求解。在输出时检验其输出结果是否满足即可

        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;//回溯回来修改标志防止影响取值
			}
		}	
	}
posted @ 2021-11-01 16:02  kki_m  阅读(711)  评论(0)    收藏  举报