八皇后问题(递归回溯+迭代回溯)

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


#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<windows.h>
#define ms(x,y) memset(x,y,sizeof(x))
const int MAXN=1000+10;
const int INF=1<<30;
using namespace std;
int vis[MAXN][MAXN];
int c[60]; //c[i] 表示第i行的皇后所在的列号
int cnt;

/* -------------------------------------------------------------- */

void eight_queen(int cur, int n) //递归1
{
	int i, j, ok;
	if(cur == n) {
		cnt++;
		/*
		for(i=0; i<n; i++){
			for(j=0; j<n; j++){
				if(j == c[i]) printf("# ");
				else printf(". ");
			}
			printf("\n");
		}
		printf("\n%d\n\n", cnt);
		*/
		return;
	}
	for(i=0; i<n; i++){
		c[cur] = i;
		ok=1;
		for(j=0; j<cur; j++){
			if(i == c[j] || cur - i == j - c[j] || cur + i == j + c[j]){
				ok=0; 
				break;
			}
		}
		if(ok) eight_queen(cur+1, n);
	}
}

/* -------------------------------------------------------------- */

void eight_queen1(int cur, int n) //递归2
{
	int i, j;
	if(cur == n){
		cnt++;
		/*
		for(i=0; i<n; i++){
			for(j=0; j<n; j++){
				if(j == c[i]) printf("# ");
				else printf(". ");
			}
			printf("\n");
		}
		printf("\n%d\n\n", cnt);
		*/
		return;
	}
	for(i=0; i<n; i++){
		c[cur] = i;
		if(!vis[0][i] && !vis[1][cur+i] && !vis[2][cur-i+n]){
			vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
			eight_queen1(cur+1, n);
			vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
		}
	}
}

/* -------------------------------------------------------------- */

bool Judge(int r, int c, int n) //迭代
{
	if(!vis[0][c] && !vis[1][r + c] && !vis[2][r - c + n]){
		vis[0][c] = vis[1][r + c] = vis[2][r - c + n] = 1;
		return 1;
	}
	return 0;
}

void SetZero(int r, int c, int n)
{
	vis[0][c] = vis[1][r + c] = vis[2][r - c + n] = 0;
}

void eight_queen2(int cur, int n)
{
	int i, j, C, R;
	c[cur] = -1;
	while(cur >= 0)
	{
		c[cur]++;
		while(c[cur] < n && !Judge(cur, c[cur], n)) //在该行寻找适合的列
			c[cur]++;
		if(c[cur] < n){
			if(cur == n - 1){
				cnt++;
				/*
				for(i=0; i<n; i++){
					for(j=0; j<n; j++){
						if(j == c[i]) printf("# ");
						else printf(". ");
					}
					printf("\n");
				}
				printf("\n%d\n\n", cnt);
				*/
				SetZero(cur, c[cur], n);
			}
			else{ //处理下一行皇后
				cur++;
				c[cur] = -1;
			}
		}
		else{ //回溯
			cur--;
			SetZero(cur, c[cur], n);
		}
	}
}

/* -------------------------------------------------------------- */

int main()
{
	int n = 13;
	FILETIME beg,end;
	GetSystemTimeAsFileTime(&beg);
	eight_queen2(0, n);
	GetSystemTimeAsFileTime(&end);
	int dur = 100*(end.dwLowDateTime-beg.dwLowDateTime);
	printf("%d\n", dur);
	printf("%d\n", cnt);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值