(hdu step 4.3.6)N皇后问题(使用DFS来解决)

来源:互联网 发布:大浦洞导弹 知乎 编辑:程序博客网 时间:2024/05/20 09:48

题目:

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
1850
 
Sample Output
19210
 
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++;//棋子成功拜访的方案数+1return;}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;//将标记设置为falsebreak;}}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;}




2 0
原创粉丝点击