深度搜索(dfs)+典型例题(八皇后)

深度优先搜索简称深搜,从起点出发,走过的点要做标记,发现有没走过的点,就随意挑一个往前走,走不了就回退,此种路径搜索策略就称为“深度优先搜索”,简称“深搜”。

如上面的图所示:加入我们要找一个从V0到V6的一条最短的路径。我们可以看到有许多的路我们可以走。

V0——V3——V5——V6;

V0——V3——V1——V4;

V0——V3——V1——V2——V6;

V0——V1——V4;

V0——V1——V3——V5——V6;

V0——V1——V2——V6;

V0——V2——V6;

前两组,是从节点V3开始分的,然后遍历了后面的所有路径,然后找到了我们需要的解。

从第三条路径我们就可以看到,到了V4之后就没有路了,那么我们就需要返回到V1找下一条路径。

V1节点所有的路径我们就都找完了,就开始找V2节点的路径了。由于我们一开始不知道哪一条路可以走到V6和不知道哪一条路径最短,所以我们需要找出所有的路,然后再来判断哪一条路最短。

上面我们找到了所有的路径,然后判断最小的路径是V0——V2——V6,这就是最优解。

深搜的基本模板:

int search(int t)
{
    if(满足输出条件)
    {
        输出解;
    }
    else
    {
        for(int i=1;i<=尝试方法数;i++)
            if(满足进一步搜索条件)
            {
                为进一步搜索所需要的状态打上标记;
                search(t+1);
                恢复到打标记前的状态;//回溯
            }
    }
}

 

总结:深搜就是要找到所有可能的解,然后再来找到最优解,需要我们遍历所有的路径。

典型例题(八皇后):链接:https://www.luogu.org/problem/P1219

题目描述

检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 6

列号 2 4 6 1 3 5

这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

输入格式

一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

输入输出样例

输入 #1
6
输出 #1
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

对于该题目,因为我们不知道怎样来放这个点,所以我们需要将所有的点都试一下,防止漏掉哪一个点:

题解:

#include<iostream>
using namespace std;
int sum=1;
int A[200]={0},B[200]={0},C[200]={0},D[200]={0};//表示横行,B表示纵行,C表示左下到右上的对角线,D表示左上到右下的对角线 
int n;
int print()//输出前三个 
{
    
    if(sum<=3)
    {
        for(int i=1;i<=n;i++)
         cout<<A[i]<<" ";     
         cout<<endl;
    }
    sum++;
 }
 void dfs(int i)
 {
      if(i>n)
      {
          print();
          return ;
       } 
     if(i<=n)
     {
         for(int j=1;j<=n;j++)
         {
             if(B[j]!=1&&C[j-i+n]!=1&&D[i+j]!=1)
             {
                 A[i]=j;//记录纵列的值 
                 B[j]=1;//标记纵列 
                 C[j-i+n]=1;//标记对角线 
                 D[i+j]=1;//标记对角线 
                 dfs(i+1);//接着搜下一个点 
                 B[j]=0;//清除记忆 
                 C[j-i+n]=0;
                 D[j+i]=0;
             }
         }
     }
 }
 int main()
 {
     cin>>n;
     dfs(1);
     cout<<sum-1;
     return 0;
 }
  

 

posted @ 2019-08-18 19:01  香格里拉太子zo  阅读(1367)  评论(1编辑  收藏  举报