回溯算法

本文通过八皇后问题详细介绍了回溯法的基本思想及其实现过程。利用动态穷举法(剪枝)来减少不必要的搜索,提高了求解效率。
       回溯法,简单理解就是有源可溯。基本思想要借鉴穷举法,但是它不是一味地穷举,当发现某一步不符合条件时,这一步后面的穷举操作就不进行了(俗称“剪枝”),我自己把它叫做动态穷举法。假设第一个步骤可行,那么执行第二个步骤,第三个......如果其中第三个步骤不行,那么我们再回过来(回溯),第二个步骤换一种方法尝试,然后再重新第三个步骤,第四个......直到完成任务要求为止。

这里,以八皇后问题为例。试图把回溯法讲清楚。
注意:递归应该是一种算法结构,回溯法是一种算法思想。


八皇后问题
       八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

解题思想
       我们采用回溯法来解决这个问题。还记得我说的动态穷举法(“剪枝”)?那么我们就开始穷举吧。过程请看下图。八个皇后,每个皇后放一行,那么我们要确定的就是每行皇后要放的列的位置。对于第一行,假设把皇后放在第一列(这里就开始了一个for循环了)。第一步当然满足,然后我们看第二行(又开始一个for循环啦),假设把第二个皇后放在(2,1)(行,列)处,不行(“剪枝”)!那继续for,放在(2,2)处,不行(“剪枝”)!继续for,放在(2,3)处。Bingo!那我们进行第三步,第四步....也许,在第三步当中,执行完第三步的八次for循环后,仍未有合理的答案。那么就得返回第二步了。这时候,把第二个皇后放在(2,4)处。继续......

#include<iostream>
#include<Windows.h>
using namespace std;

int m[8][8];
int queen[8];

void print()
{
	system("cls");
	cout << "八皇后问题动态演示\n";
	cout << "------------------------\n";
	for (int outer = 0; outer < 8; outer++)
	{
		if (queen[outer] != -1)
		{
			for (int inner = 0; inner < queen[outer]; inner++)
				cout << " . ";
			cout << " # ";
		}
		for (int inner = queen[outer] + 1; inner < 8; inner++)
			cout << " . ";
		cout << endl;
	}
}

bool is_meet(int i,int j)
{
	int r, c;
	for (r = 0; r < i; r++)
	{
		c = queen[r];
		if (j == c)
			return 0;
		if ((i + j) == (c + r))
			return 0;
		if ((j-i) == (c - r))
			return 0;
	}
	return 1;
}

void findQueen(int i)
{
	Sleep(1000);
	print();
	int j;
	for (j = 0; j < 8; j++)
	{
		if (is_meet(i, j))
		{
			queen[i] = j;
			if (i == 7)
			{
				//print();
				return;
			}
			else
				findQueen(i+1);
		}
		queen[i] = -1;
	}
}

int main()
{
    memset(queen, -1, 8 * sizeof(int));//这里是赋-1,故不会出错,要清楚memset是依次对单个字节进行赋值
    findQueen(0);
    system("pause");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值