回溯法——八皇后问题

在写递归枚举程序前,要、、、对、、、 应该对节点数进行粗略的统计;

当吧问题分成若干步骤并递归求解时,如果当前步骤没有合法选择,返回上一级调用,这个现象称为回溯

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
int tot, C[maxn], n ;
void search(int cur)
{
	if (cur == n)
	{
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				cout << (C[i] == j ? "*" : "#") << (j == n - 1 ? "\n" : " ");
		cout << endl;
		tot++;
	}
	else for (int i = 0; i < n; i++)
		{
			int ok = 1;
			C[cur] = i;
			for (int j = 0; j < cur; j++)
				if (C[cur] == C[j]
				        || cur - C[cur] == j - C[j]
				        || cur + C[cur] == j + C[j])//判断对角线
				{ok = 0; break;}
			if (ok) search(cur + 1);
		}
}
int main(int argc, char const *argv[])
{
	while (cin >> n)
	{
		memset(C, 0, sizeof(C));
		tot = 0;
		search(0);
		cout << tot << endl;
	}
	return 0;
}

然而,程序还可以进一步提升效率,利用二位数组保存记录判断当前点是否符合要求

vis数组表示已经放置的皇后占据了那些列主对角线,副对角线

用毕注意及时回复原状,应为回溯的过程不会影响全局变量

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
int n, vis[maxn][maxn], c[maxn], tot;
void search(int cur)
{
	if (cur == n)
	{
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				cout << (c[i] == j ? "*" : "#") << (j == n - 1 ? "\n" : " ");
		cout << endl;
		tot++;
	}
	else for (int i = 0; i < n; i++)
		{
			if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n])
			{
				c[cur] = i;
				vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1;
				search(cur + 1);
				vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0;
			}
		}
}
int main(int argc, char const *argv[])
{
	while (cin >> n)
	{
		memset(c, 0, sizeof(c));
		memset(vis, 0, sizeof(vis));
		tot = 0;
		search(0);
		cout << tot << endl;
	}
	return 0;
}


你可能感兴趣的:(回溯法——八皇后问题)