关闭

回溯算法之 N皇后问题

标签: 算法search
745人阅读 评论(0) 收藏 举报
分类:
// n皇后
#include <stdio.h>
#include <string.h>

#define MAX 15

int n;    //n queen
int cur;  //cur row
int A[MAX];    //the ith row's queen put in the A[i]th column
int tot = 0;    // total nums


//cur 为当前遍历到的行。
//从第1~n列中选择一列,使当前皇后放到此位置时,与已经放好的1~cur-1行的皇后不冲突(即不在同一行、同一列、两个对角线上)
void search(int cur)
{
	int i, j;
	if (cur==n+1)        //找到n个皇后的位置,打印出
	{
		for (i=1; i<cur; i++)
			printf("%d ", A[i]);
		printf("\n");
		tot++;
		return;
	}
	for(i=1; i<=n; i++)       //遍历1~n列找到其中的一列可以用来放置当前的皇后
	{
		int ok = 1;
		A[cur] = i;
		for (j=1; j<cur; j++)       //判断是否与之前已经放置的1~cur-1行的皇后有冲突
			if (A[cur] == A[j] || cur-A[cur] == j-A[j] || cur+A[cur] == j+A[j])    //在同一列/两个对角线上
			{   ok = 0;  break;   }

		if (ok)      //找到继续需找下一个皇后
			search(cur+1);
	}
}


int main()
{
	while (scanf("%d", &n)!=EOF)
	{
		memset(A, 0, sizeof(A));
		tot = 0;

		search(1);
		printf("%d\n", tot);
	}
	return 0;
}



注意到上面程序中判断第i列是否能放当前cur行的皇后的效率比较低,可以改进。

用一个全局变量vis[2][ ] 来保存某列、某主对角线、某副对角线已经被皇后占用。

这样就可以直接判断第i行是否可以放当前的皇后了。

void search2(int cur)
{
	int i, j;
	if (cur == n+1)
	{
		for (i=1; i<cur; ++i)
			printf ("%d ", A[i]);
		printf ("\n");
		tot++;
		return ;
	}


	for (i=1; i<=n; ++i)
	{
		if (!vis[0][i] && !vis[1][i+cur] && !vis[2][cur-i+n])      //判断是否可以放置当前皇后(效率比前面的高)
		{
			A[cur] = i;
			vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 1;     //修改全局变量的值使当前皇后放置位置的列、两条对角线被占用
			search2(cur+1);
			vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 0;     //回溯,一定要将前面修改过的值改回来!
		}
	}
}


第一次写这个程序时将循环计数变量i,j误设置为全局变量,导致程序运行结果不正确。这是一个递归程序,i,j应该为局部变量,才不会导致进一步递归时程序破坏上一次递归栈的局部数据!!



参考文献:《算法竞赛入门经典》 刘汝佳 编著


0
0
查看评论

回溯法算法步骤&n皇后问题的详细程序(C++)

/* 回溯法有“通用解题法”之称,可以系统的搜索问题的所有解,既有系统性也有跳跃性。 它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至洁空间树 的任一结点时,先判断该结点是否包括该问题的解,如果肯定不包含,则跳过对以该结点为 根的子树的搜索,逐层向其祖先结点回溯;否...
  • zhangchao3322218
  • zhangchao3322218
  • 2012-10-19 18:47
  • 6393

N皇后问题 HDU 杭电2553【递归回溯】

Problem Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 你的任务是,对于给定的N,求出有多少种合法的放置方法。 Input 共有若干行,每行一个正整数N≤10,...
  • yuzhiwei1995
  • yuzhiwei1995
  • 2015-08-03 17:45
  • 563

回溯法解决N皇后问题——递归与非递归求解

回溯法其实也是一种搜索算法,它可以方便的搜索解空间。  回溯法解题通常可以从以下三步入手:  1、针对问题,定义解空间  2、确定易于搜索的解空间结构  3、以深度优先的方式搜索解空间,并在搜索的过程中进行剪枝  回溯法通常在解空间树上进行...
  • leepwang
  • leepwang
  • 2012-06-21 12:58
  • 2079

回溯算法之n皇后问题

n皇后问题输出8皇后问题所有结果。输入 n:棋盘的行列 输出 每个结果第一行是No n:的形式,n表示输出的是第几个结果;下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格。不同的结果中,先输出第一个皇后位置靠前的结果;第一个皇后位置相同,先输出第二个皇后位置靠前的结果;依次类推。输入...
  • u011040361
  • u011040361
  • 2015-04-20 21:56
  • 234

经典回溯算法之n皇后问题

这是来源于国际象棋的一个问题。n后问题要求在一个n×n格的棋盘上放置n个皇后,使得它们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一条斜线上的其他任何棋子。因此,n后问题等价于要求在一个n×n格的棋盘上放置n个皇后,使得任何两个皇后不能被放在同一行...
  • Luyanc
  • Luyanc
  • 2017-09-30 12:25
  • 284

经典回溯算法之N皇后问题

背景问题:http://acm.hdu.edu.cn/showproblem.php?pid=2553 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 你的任务是,对于给定的N,求出有多少种合法的放置方法。 ...
  • theArcticOcean
  • theArcticOcean
  • 2016-01-06 16:48
  • 452

回溯算法之N皇后问题

一、问题描述 N皇后问题,就是把N个皇后放到NXN的棋盘上,使她们不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。 二、问题分析 典型的回溯问题; queens[k]表示皇后k放在queens[k]位置上。 三、算法代码 算法参数int [] queens可以随意传值,它们的长度...
  • tterminator
  • tterminator
  • 2016-03-14 22:54
  • 557

回溯算法n皇后问题

这是一道考查应聘者综合能力的问题,其中包含了算法的设计、UI的设计、接口的设计等问题,当然在具体面试中没有时间让应聘者完成整个设计和编码,但是面试官往往通过了解应聘者的设计思路和工作步骤来考查应聘者的能力。本节将具体分析这道程序设计题。  所涉及到的知识点•   ...
  • manchaozhao
  • manchaozhao
  • 2008-12-22 13:38
  • 372

N皇后问题--回溯算法的经典实例

问题描述: 皇后是国际象棋中威力最大的棋子。在下面所示的棋盘上,皇后可以攻击位于箭头所覆盖位置的所有棋子。我们能不能把N个皇后放在棋盘(N×N)上,它们中的任何一个都无法攻击其余的皇后?请编写程序输出皇后的摆放方案,并找出一共有几种方法。 问题分析: 编程即是先找到问题的解决方法,然后...
  • shengabc
  • shengabc
  • 2016-04-11 16:50
  • 4858

N皇后问题——回溯算法

// programme1.cpp : Defines the entry point for the console application. //Author: C.J //...
  • wlcgangcunningci
  • wlcgangcunningci
  • 2013-12-09 08:55
  • 364
    个人资料
    • 访问:369213次
    • 积分:3420
    • 等级:
    • 排名:第11613名
    • 原创:73篇
    • 转载:0篇
    • 译文:6篇
    • 评论:93条
    公告
    最新评论
    友情链接