题目:
N皇后问题 |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
Total Submission(s): 568 Accepted Submission(s): 332 |
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 |
Author cgf |
Source 2008 HZNU Programming Contest |
Recommend lcy |
题目分析:
这道题是N皇后问题。所谓的N皇后问题无非是在一个N*N的棋盘上,摆放N个棋子。每个棋子两两不在同一行、同一列、同一斜线上。需要注意的是,在这道题中只开了一维数组map[]用来存储棋子的拜访情况。也就是在某一维中,他已经限定死了其摆放情况(如这道题中第i个棋子就必然放在第i行)。
代码如下:
/*
* f.cpp
*
* Created on: 2015年2月25日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 11;
/**
* map[]:用来存储第k个期指放在第几列.
* 需要注意的是map[k]=j。表示的是第k个棋子放在第j列.
* 同时,它在第k行
*/
int map[maxn];
bool visited[maxn];//用於标记某一列是否已经访问过
int result[maxn];//打表,保存各个结果
bool flag;//用于标记某一个棋子是否成功
int n;
int ans;//n为某一具体值时,棋子摆放的方案数
/**
* 深搜.
* k:表示目前放到了第几个棋子
*/
void dfs(int k) {
if (k == n + 1) {//如果k已经达到n+1.表示所有棋子已经摆放完毕
ans++;//棋子成功拜访的方案数+1
return;
}
int i;
int j;
for (i = 1; i <= n; ++i) {//遍历所有列
if (visited[i] == false) {//如果该列没有被访问
map[k] = i;//尝试将第k个棋子放在第i列(第k个旗子肯定是在第k行的)
flag = true;//比尝试标记为成功
for (j = 1; j <= k - 1; ++j) {//遍历之前的k-1个棋子
/**
* 如果他们在同一斜线上(在这种实现方式中,他已经确保了没一个棋子肯定会与其他棋子在不同行、不同列.
* 这时候我们只需要判断一下它们是否在同一斜线上即可)
*/
if (abs(map[k] - map[j]) == abs(k - j)) {
flag = false;//将标记设置为false
break;
}
}
if (flag == true) {//如果flag为true,表示第k个棋子可以摆放成功
visited[i] = true;//将第i列标记为已经访问过
dfs(k + 1);//开始拜访第k+1棋子
visited[i] = false;//将第i列重新标记为未访问过.用于其他情况
}
}
}
}
int main() {
int i;
/**
* 打表各种情况
*/
for (i = 1; i <= 10; ++i) {
memset(visited, false, sizeof(visited));
flag = false;
n = i;
ans = 0;
dfs(1);
result[n] = ans;
}
while (scanf("%d", &n) != EOF, n) {
printf("%d\n", result[n]);
}
return 0;
}