TZOJ 4435 n皇后问题(回溯)

描述

在 n×n 的国际象棋棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后任两个皇后都不能处于同一条横行、纵行或斜线上)

输入

输入有多组(直到-1结束)

每组一行 一个整数 n(0<n<11)代表皇后的个数。

输出

每组测试数据间输出一个换行。

对于每组数据,如果存在一个棋谱(使得n个皇后不会相互攻击),先输出这是第几种棋谱,然后输出该棋谱。当全部棋谱都输完时,最后输出该组总共摆放的棋谱数。

样例输入

1
2
4
-1

样例输出

case1:
1
There are 1 kinds of

There are 0 kinds of

case1:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
case2:
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
There are 2 kinds of

提示

存放皇后时,按列优先的顺序从上往下从左至右的顺序遍历。

题意

在 n×n 的国际象棋棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后任两个皇后都不能处于同一条横行、纵行或斜线上),输出所有可能的棋盘,最后输出总数

题解

回溯,往前试探一步,判断是否可行,再试探

代码
 1 #include<stdio.h>
 2 #include<string.h>
 3 int n,k;
 4 int pos[11];//pos[i]=j表示第i行的皇后在第j列
 5 int abs(int x){return x>0?x:-x;}
 6 bool st(int now)
 7 {
 8     for(int i=0;i<now;i++)
 9         if(pos[i]==pos[now]||abs(pos[i]-pos[now])==abs(i-now))//和前几个在同一列,在同一斜
10             return false;
11     return true;
12 }
13 void print()
14 {
15     printf("case%d:\n",++k);//k代表个数
16     for(int i=0;i<n;i++)
17     {
18         if(pos[i]==0)
19             printf("1");
20         else
21             printf("0");
22         for(int j=1;j<n;j++)
23         {
24             if(pos[i]==j)
25                 printf(" 1");
26             else
27                 printf(" 0");
28         }
29         puts("");
30     }
31 }
32 void trail(int now)//递归回溯,now表示第几个试探
33 {
34     if(n==now)//填满n个结束
35     {
36         print();
37         return;
38     }
39     for(int j=0;j<n;j++)
40     {
41         pos[now]=j;//先填上,试探
42         if(st(now))//可行就先选这个数
43             trail(now+1);//试探下一个
44     }
45 }
46 int main(){
47     int o=0;
48     while(scanf("%d",&n)!=EOF,n!=-1)
49     {
50         if(o++)puts("");
51         memset(pos,0,sizeof(pos));
52         k=0;
53         trail(0);
54         printf("There are %d kinds of\n",k);
55     }
56     return 0;
57 }

posted on 2018-02-05 00:10  大桃桃  阅读(282)  评论(0)    收藏  举报

导航