[USACO1.5]八皇后 Checker Challenge

题目链接 https://www.luogu.com.cn/problem/P1219

没错我又做的dfs.........因为总感觉没大理解不太会写.......那怎么办嘛......


 

对于八皇后问题我们可以把它转化为精确覆盖的问题:

1、每行只能放一个皇后

2、每列只能放一个皇后

3、每个“/”只能放一个皇后

4、每个“\”只能放一个皇后


 

本道题最重要的就是记录下皇后占领的格子(打标记的思想),通过标记判断下一个皇后能否在某个位置。如果可以,继续搜索下一个皇后的位置;如果不可以,则清除标记返回上一步,继续搜索。

我的第一想法是用四个一维数组分别表示行、列、左斜、右斜,记录这四条线是否被标记。看到有用二维数组的但是好像会TLE,我也没试。

(还没写完但是实验室要关门了我要走了明天再写!)

(第二天:我已经忘了我想写什么了。。。)


 

更:

关于 第21行代码中,对角线和反对角线为什么分别为 i+j 和 i-j+n ?

关于 为什么要清除标记?

因为要回溯,对于不能满足条件的点不再进行搜索,并将之前的标记清除,再对下一个点搜索。


 

 

放AC代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,sum=0;
 4 int a[50],b[50],c[50],d[50];//——、|、/、'\'
 5 void dfs(int i)
 6 {
 7     if(i>n)//如果超过n行
 8     {
 9         sum++;//表明已经找到一个解,则解的总数+1
10         if(sum>3) return;
11         else//输出前三个解
12         {
13             for(int i=1;i<=n;i++)
14                 cout<<a[i]<<" ";
15             cout<<endl;
16             return;
17         }
18     }
19     for(int j=1;j<=n;j++)//尝试可能的位置
20     {
21         if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))//如果纵列和对角线没有都没有被占领
22         {
23             a[i]=j;//标记第i排是第j个
24             b[j]=-1;//占领纵列
25             c[i+j]=-1;
26             d[i-j+n]=-1;
27             dfs(i+1);//深入搜索下一个皇后
28             b[j]=0;//清除标记
29             c[i+j]=0;
30             d[i-j+n]=0;
31         }
32     }
33 }
34 int main()
35 {
36     cin>>n;
37     dfs(1);
38     cout<<sum;
39     return 0;
40 }

 

posted @ 2022-03-24 21:22  爱吃虾滑  阅读(53)  评论(0编辑  收藏  举报