洛谷P1219 [USACO1.5]八皇后 Checker Challenge(回溯深搜)

Posted 江上舟摇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1219 [USACO1.5]八皇后 Checker Challenge(回溯深搜)相关的知识,希望对你有一定的参考价值。

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

n皇后问题我们前面已经讲过,这个题在原来的基础上要求输出前三个解的具体放置方法,所以稍稍会有些不同

这里采用的是回溯标记法,即用数组来储存解的同时,标记已经求解过的数组,然后回溯清0,重新来过。

比较深刻的解释就是:

为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回上一步重新选择条件,继续向前探索,如此反复进行,直至得到解或证明无解。

Ta的特点如下:

1.可以在借助系统栈储存状态

2.空间为O(深度)

3.可以剪枝

4.比较容易实现

5.不易判重

这个就是我们在这道题中的主要思路。如果在准备放置皇后的时候发现,这一行都没有合适的位置,那么我们就“报错”:退回上一状态,重新来过。

为了让皇后们可以吃“后悔药”,我们就必须给她们留下后路——曾经打过标记的地方都撤销掉,让她们有路可回。

tip:

对于左对角线来讲横纵坐标的和是一定的,而右对焦线的行列之差是一定的,但是为了确保行列之差是个正数,我们需要在加上一个n以保证恒正。

另外,数组最好开大一点

参考代码及注意事项如下:

 #include<bits/stdc++.h>
 using namespace std;
 int n,ans=0;
 int row[1500];//表示第i行第j列 放皇后
 int col[1500];//储存列
 int l[1500];//储存左对焦线,表示left
 int r[1500];//储存右对焦线,表示right 
 void print()
 
     ans++;
  if(ans<=3)
  
      for(int i=1;i<=n;i++)
      cout<<row[i]<<" ";
      cout<<endl;
  //输出前三组解
 
 void dfs(int i)
 
  if(i>n)
  
      print();
      return ;
  
  for(int j=1;j<=n;j++)
  
      if(col[j]==0&&l[i+j]==0&&r[i-j+n]==0)//未被标记的 
      
          row[i]=j;//放皇后 
          col[j]=1;//标记 
          l[j+i]=1;
          r[i-j+n]=1;//以上是“占领”操作
          dfs(i+1);//下一行
          col[j]=0;//以下是回溯操作
          l[j+i]=0;
          r[i-j+n]=0;
      
  
 
 int main ()
 
      cin>>n;
      dfs(1);//开始
      cout<<ans<<endl;//结束
      return 0;//告成!
 

除此之外,我还在网上了解到一个手动开o2优化的方法:#pragma GCC optimize(2),o3也是同这个方法差不多。

但是竞赛主办方如果没开就不要写了,容易造成错误。

另外,从今天开始每日一题加强训练并且复习一到三篇博客,要真真正正为自己的acm,蓝桥杯备赛,更是为自己的前途和理想备战了。

写在最后:也许生活没有你想象的这么美好,但请相信,诗会有的,远方也会有的,而你现在所要做的,就是好好努力,好好学习,为了自己的梦想,奔向远方,加油加油!

戒骄戒躁,任重道远

以上是关于洛谷P1219 [USACO1.5]八皇后 Checker Challenge(回溯深搜)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1219 八皇后

洛谷 P1219 八皇后经典DFS,温习搜索

洛谷 P1219 八皇后

洛谷 P1219 八皇后 题解

P1219 八皇后

P1219 八皇后