回溯算法最经典的问题是八皇后问题。题意很简单,给定一个n*n棋盘,放置n个皇后,满足任意两个皇后不能在同一行,同一列或者同一对角线上。显然,暴力算法可以求解这个问题。回溯算法相较于暴力算法的一个优点是从第一个状态开始,执行深度优先搜索,如果当前状态不满足,则立即停止并返回上一个状态。利用递归可以非常好地执行这一类算法。
下面是八皇后问题的代码:
#include<iostream> #include<cmath> using namespace std; int *route; int result; bool is_OK(int s) { int i; for (i = 1; i<s; i++) if (route[i] == route[s] || abs(i - s) == abs(route[i] - route[s])) return false; return true; } void queen(int n, int s) { if (s > n) result++; else { int col; for (col = 1; col <= n; col++) { route[s] = col; if (is_OK(s)) queen(n, s + 1); } } } int main() { int n; int i; while (scanf("%d", &n) == 1 && n>0) { route = new int[n + 1]; result = 0; queen(n, 1); printf("%d\n", result); } return 0; }View Code
在SOJ 1082(http://acm.scu.edu.cn/soj/problem.action?id=1082)这道题目中,有些状态已经初始化了。只需对上述代码做一些简单的修改,代码如下:
#include<iostream> #include<cmath> using namespace std; int *route; int *iniPos; int result; bool is_OK(int s) { if (s == 1 || abs(route[s] - route[s - 1]) <= 1) return true; else return false; } void queen(int n, int s) { if (s > n) result++; else { if (iniPos[s] == 0) { int row; for (row = 1; row <= n; row++) { route[s] = row; if (is_OK(s)) queen(n, s + 1); } } else { route[s] = iniPos[s]; if (is_OK(s)) queen(n, s + 1); } } } int main() { int n; int i; while (scanf("%d", &n) == 1 && n) { route = new int[n + 1]; iniPos = new int[n + 1]; result = 0; for (i = 1; i <= n; i++) scanf("%d", &iniPos[i]); queen(n, 1); printf("%d\n", result); } return 0; }View Code
参考以下博文:
https://www.cnblogs.com/bigmoyan/p/4521683.html
https://blog.csdn.net/eric_e/article/details/80457976