hdoj 2553 N皇后问题【回溯+打表】

N皇后问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11855    Accepted Submission(s): 5301


Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

 

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
 

Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
 

Sample Input
1
8
5
0
 

Sample Output
1
92
10
做题时需要注意以下几点:
    (1)本行所放的皇后位置不能与上一行同列
    (2)不能与上一行在主对角线上
    (3)不能与上一行在副对角线上
判断是否在对角线上(此处不会  参考的刘汝佳编著的算法竞赛入门经典)
根据下表判断主对角线 条件cur-a[cur]==j-a[j]可以判断主对角线
0 1 2 3 4 5 6 7
-1 0 1 2 3 4 5 6
-2 -1 0 1 2 3 4 5
-3 -2 -1 0 1 2 3 4
-4 -3 -2 -1 0 1 2 3
-5 -4 -3 -2 -1 0 1 2
-6 -5 -4 -3 -2 -1 0 1
-7 -6 -5 -4 -3 -2 -1 0

 

 

 

 

 

 

 

 

格子(x,y)的y-x值标示了主对角线

根据下表判断另一条对角线 条件cur+a[cur]==j+a[j]判断副对角线

0 1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9 10
4 5 6 7 8 9 10 11
5 6 7 8 9 10 11 12
6 7 8 9 10 11 12 13
7 8 9 10 11 12 13 14

 

 

 

 

 

 

 

格子的(x,y)的x+y值标示了副对角线

以上两图为棋盘的对角线标示

附上AC代码:

#include<stdio.h>
#include<string.h>
#define MAX 15
int a[MAX];
int s[MAX];
int vis[MAX];
int n,t,tot;
void dfs(int cur)//cur代表行数
{
	int i,j;
	if(cur==n)
	{
		tot++;//记录当前行数时符合题意的摆放个数 
	}
	else
	{
		for(i=0;i<n;i++)
		{
			int ok=1;
			a[cur]=i;//尝试将皇后放在第cur行的第i列 
			for(j=0;j<cur;j++)//判断 是否和前面的皇后冲突 
			{
				if(a[cur]==a[j]||cur-a[cur]==j-a[j]||cur+a[cur]==j+a[j])//判断上一行和对角线上是否符合题意 
				{
					ok=0;//与上一行皇后有冲突则将皇后放在下一列继续判断 
					break;
				}
			}
			if(ok)//如果满足条件 
			dfs(cur+1);//继续回溯 
		}
	}
}
int main()
{
	int m,j,i,k;
	memset(a,0,sizeof(a));
	memset(s,0,sizeof(s));
	for(n=1;n<=10;n++)
	{
		tot=0;
		dfs(0);
		s[n]=tot;//打表记录对应行数时符合题意的个数 
	}
	while(scanf("%d",&t),t)
	{
		printf("%d\n",s[t]);
	}
	return 0;
}

 

 

posted @ 2015-06-29 10:57  非我非非我  阅读(626)  评论(0编辑  收藏  举报