来来来!经典的八皇后!

Posted on 2015-05-20 10:32  Maples7  阅读(581)  评论(0编辑  收藏  举报

八皇后

(1.0/1.0 points)
题目描述

8X8的国际象棋棋盘上被挖了一些洞,这些洞不能放棋子,求八皇后问题的摆放方案,输出一种方案即可

输入格式

棋盘用.表示正常格子,用#表示被挖掉的洞,一共8行8列

输出格式

输出从上到下的每一行的皇后所在列号(1-8)

注意:只输出列号,只输出列号,最后的输出应该只是8个数字,第i个数字表示第i行的皇后在第几列,中间以空格隔开。

样例输入
........
..##....
####....
........
........
........
........
....####
样例输出
6 2 7 1 4 8 5 3



 1 #include <iostream>
 2 using namespace std;
 3 
 4 const int offset = 9;
 5 
 6 int    row[9];
 7 bool col[9];
 8 bool k_eq_1[17];
 9 bool k_eq_minus1[17];
10 char stage[9][9];
11 
12 void tryRow(int i)
13 {
14     if (i == 9)
15     {
16         for (int k = 1; k < 9; k++)
17             cout << row[k] << " ";
18         exit(0);
19     }
20     for (int j = 1; j < 9; j++)
21     {
22         if (stage[i][j] != '#' && col[j] && k_eq_1[i - j + offset] && k_eq_minus1[i + j])
23         {
24             row[i] = j;
25 
26             col[j] = false;
27             k_eq_1[i - j + offset] = false;
28             k_eq_minus1[i + j] = false;
29 
30             tryRow(i + 1);
31 
32             k_eq_minus1[i + j] = true;
33             k_eq_1[i - j + offset] = true;
34             col[j] = true;
35         }
36     }
37 }
38 
39 int main(void)
40 {
41     for (int i = 1; i < 9; i++)
42     {
43         col[i] = true;
44         for (int j = 1; j < 9; j++)
45         {
46             cin >> stage[i][j];
47             k_eq_1[i - j + offset] = true;
48             k_eq_minus1[i + j] = true;
49         }
50     }
51 
52     tryRow(1);
53 
54     return 0;
55 }

只是最经典的递归回溯深搜版,值得注意的就是 offset 。

一条正对角线上 i-j 值都是相同的,所以可以用 i-j 表示某一正对角线是否被占用;

同理,副对角线 i+j 都是相同的。

offset 是为了使正对角线(i-j)与副对角线(i+j)落入相同的区间,好被数组统一处理而设定的,也就是正对角线的偏移量。由于所有 i-j 都偏移,所以不影响正确性。