8.11做题总结

(搜索题目题解) 

一.(全排列)深搜模板题 

老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么?

输出1~8的全排列

题解:全排列就是深搜的模板题,深搜的特点是一条道走到黑(也就是对应了“深”的特点),如果走不通或者已经走到底之后就回溯,再继续搜索。

深搜(dfs)是通过递归的方法实现的,深搜的形数是搜索的深度(也就是层数)

深搜具体思路:

1.首先判断深度是否到达了最底层,也就是深度是否到达了8,如果到达最底层就将搜索到的全排列输出。

2.如果没有到达最底层,就从1到8循环,看哪一个数字没有用过,就将这一位设置成没有用过的数字,然后将这一个数字标记成用过的,然后再递归搜索下一层,搜索到最底层之后回溯的时候不要忘记将已经标记成用过的数字改成未标记的(这一步很重要!!!)

#include<bits/stdc++.h>
using namespace std;

const int N=100;
int a[N],vis[N],dep=1;//a[N]是全排列的顺序,vis[N]是标记是否这个数字是否用过,dep是深度

void dfs(int dep){
    if(dep>8){
        for(int i=1;i<=8;i++) cout<<a[i]<<' ';
        cout<<endl;
        return ;
    }
    for(int i=1;i<=8;i++){
        if(!vis[i]){         //如果vis[i]没用过,就用这个数字
        vis[i]=1,a[dep]=i;   //用过之后将这个数字标记成用过的
        dfs(dep+1);          //递归搜索下一层
        vis[i]=0;            //回溯,依次撤销最底层标记
    }
}
    return ;
 }

int main(){
    dfs(1);
    return 0;
}

二.走出迷宫(深搜)

题目描述:

小明现在在玩一个游戏,游戏来到了教学关卡,迷宫是一个N*M的矩阵。

小明的起点在地图中用“S”来表示,终点用“E”来表示,障碍物用“#”来表示,空地用“.”来表示。

障碍物不能通过。小明如果现在在点(x,y)处,那么下一步只能走到相邻的四个格子中的某一个:(x+1,y),(x-1,y),(x,y+1),(x,y-1);

小明想要知道,现在他能否从起点走到终点。

输入描述:

本题包含多组数据。
每组数据先输入两个数字N,M
接下来N行,每行M个字符,表示地图的状态。
数据范围:
2<=N,M<=500
保证有一个起点S,同时保证有一个终点E.

输出描述:

每组数据输出一行,如果小明能够从起点走到终点,那么输出Yes,否则输出No

  输入:

3 3
S..
..E
...
3 3
S##
###
##E

输出

Yes
No

题解:本题也是考察深搜的裸题,但是本题只需要求出是否能到达终点,不需要求出方案数或者经过的坐标,因此只需要一条道走到黑,所以不需要再回溯求别的路径。

本题具体思路:

1.深搜形参是所搜索的二维坐标

2.为了方便,将下一层能走到的位置设置成一个数组xy[N][N]

3.这一层加上设置成的数组走到下一层,之后判断下一层是否在图中的范围以及这个位置是否标记过,然后再搜索下一层即可

4.不要忘记vis每次要重置!!!

代码:

#include<bits/stdc++.h>
using namespace std;

const int N=510;
char a[N][N];
int vis[N][N];
 int n,m,ai=0,aj=0;
bool flag;
int xy[10][4]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int depi,int depj){
  //  if(flag) return ;
    if(a[depi][depj]=='E'){   //如果到达终点就返回
        flag=1;
        return ;
    }
  //  vis[depi][depj]=1;
   for(int i=0;i<4;i++){
       for(int j=0;j<2;j++){
           int dx=depi+xy[i][0];
           int dy=depj+xy[i][1];
           if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!vis[dx][dy]){  //判断是否满足条件
               vis[dx][dy]=1;               //标记已经用过
               dfs(dx,dy);                 //搜索下一层
              // vis[dx][dy]=0;
               }
       }
   }
 //  cout<<"No\n";
  //  return ;
}


int main(){
   
   while(cin>>n>>m){
     flag=0;
     memset(vis,0,sizeof vis);     //每次要将vis重置为0
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]=='#'){
                vis[i][j]=1;       
            }
            else if(a[i][j]=='S'){      
                ai=i,aj=j;
            }
        }
    }
    dfs(ai,aj);
    if(flag) cout<<"Yes\n";       
    else cout<<"No\n";
       
   }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值