DFS之连通性问题+搜索顺序

简介: DFS之连通性问题+搜索顺序

1 连通性问题(内部搜索)

内部搜索一般不用恢复现场

1.迷宫

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=110;
char g[N][N];
int sx,sy,ex,ey;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
bool st[N][N];
int n;
bool dfs(int x,int y)
{
    if(g[x][y]=='#') return false;//假如是障碍
    if(x==ex&&y==ey) return true;//假如是终点了
    st[x][y]=true;//标记这个点走过
    for(int i=0;i<4;i++)//枚举四个方向
    {
        int a=x+dx[i],b=y+dy[i];
        if(a<0||a>=n||b<0||b>=n) continue;//越界
        if(st[a][b]) continue;//走过
        if(dfs(a,b)) return true;//假如后面能走到
    }
    return false;//反之走不到
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        memset(st,0,sizeof st);//清空上一层状态
        for(int i=0;i<n;i++) cin>>g[i];
        cin>>sx>>sy>>ex>>ey;
        if(dfs(sx,sy)) puts("YES");//假如能走到
        else puts("NO");
    }
   return 0;
}

2.红与黑

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=25;
int n,m,cnt;
char g[N][N];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
bool st[N][N];
void dfs(int x,int y)
{
    st[x][y]=true;//标记走过
    for(int i=0;i<4;i++)
    {
        int a=x+dx[i],b=y+dy[i];
        if(a<0||a>=n||b<0||b>=m) continue;//越界
        if(st[a][b]||g[a][b]!='.') continue;//假如走过或者不能走的
        cnt++;//连通数增加
        dfs(a,b);
    }
}
int main()
{
    while(cin>>m>>n,n||m)
    {
        memset(st,0,sizeof st);//清空上一层状态
        for(int i=0;i<n;i++) cin>>g[i];
        int x,y;
        for(int i=0;i<n;i++)//找起点
            for(int j=0;j<m;j++)
              if(g[i][j]=='@')
              {
                  x=i,y=j;
                  break;
              }
      cnt=1;//自己起点是一个点
      dfs(x,y);//找一下联通多少个
      cout<<cnt<<endl;//输出个数
    }
   return 0;
}

2.搜索顺序(外部搜索)

外部搜索一般要恢复现场

1.马走日

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n,m,sx,sy,cnt=1,ans;
bool st[N][N];
int dx[8]={-2,-1,1,2,2,1,-1,-2},dy[8]={1,2,2,1,-1,-2,-2,-1};
void dfs(int x,int y)
{
    if(cnt==n*m)//假如走完所有点
    {
        ans++;//方案加1
        return;
    }
    st[x][y]=true;//标记这个点走过
    for(int i=0;i<8;i++)//枚举八个方向
    {
        int a=x+dx[i],b=y+dy[i];
        if(a<0||a>=n||b<0||b>=m) continue;//越界
        if(st[a][b]) continue;//走过
        cnt++;//步数+1
        dfs(a,b);
        cnt--;//恢复现场步数-1
    }
    st[x][y]=false;//恢复现场
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        ans=0;
        cin>>n>>m>>sx>>sy;
        dfs(sx,sy);
        cout<<ans<<endl;
    }
   return 0;
}

2.单词接龙

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=25;
string word[N];
int g[N][N],ans=0;
int used[N];
int n;
void dfs(string dragon,int u)
{
    ans=max(ans,(int)dragon.size());//取一次龙的最长度
    used[u]++;//该位置使用加1
    for(int i=0;i<n;i++)
      if(g[u][i]&&used[i]<2)//枚举看看能不能接到该字符串后面
         dfs(dragon+word[i].substr(g[u][i]),i);
    used[u]--;//恢复现场
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>word[i];
    char start;//龙的开头
    cin>>start;
    for(int i=0;i<n;i++)//用来判断那两个可以接到一起
        for(int j=0;j<n;j++)
        {
           string a1=word[i],a2=word[j];
           for(int k=1;k<min(a1.size(),a2.size());k++)//从小开始搜看能不能接,接的越少龙越长
             if(a1.substr(a1.size()-k,k)==a2.substr(0,k))
              {
                g[i][j]=k;
                break;
              }
        }
    for(int i=0;i<n;i++)
        if(word[i][0]==start)//假如符合龙的开头
           dfs(word[i],i);
    cout<<ans<<endl;
   return 0;
}

3.分成互质组

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=15;
int p[N],n,ans=10;
bool st[N];
int group[N][N];
int gcd(int a,int b)//用来求最小公倍数,假如最小公倍数大于1说明不互质,反之互质
{
    return b?gcd(b,a%b):a;
}
bool check(int g[],int gc,int u)
{
    for(int i=0;i<gc;i++)//判断该组的所有元素是否与该元素互质
      if(gcd(p[g[i]],p[u])>1)//假如不互质
         return false;
      return true;//反之互质
}
void dfs(int g,int gc,int cnt,int start)//表示有多少组,该组有多少个元素,已用元素个数,已经用到第几个元素
{
    if(g>=ans) return;//假如组数已经大于ans,则没必要更新了
    if(cnt==n) ans=g;//g已经是最小值了,假如大于ans已经在上一步弹掉了
    int flag=true;//用来标记是否需要新开一组
    for(int i=start;i<n;i++)//找后面的元素是否能假如该组
        if(!st[i]&&check(group[g],gc,i))//假如可以加
        {
            st[i]=true;//标记该元素已经用过了
            group[g][gc]=i;//该组第gc的元素就是他
            dfs(g,gc+1,cnt+1,i+1);//下一步是组数不变,元素加1,已用元素加1,从下一个元素开始
            st[i]=false;//恢复现场
            flag=false;//说明不用新开组
        }
    if(flag) dfs(g+1,0,cnt,0);//假如新开组,则组数加1,元素0个,已用cnt个,下标从0开始,因为该组是没有元素的
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>p[i];
    dfs(1,0,0,0);//从一组开始,该组的元素0个,已用元素0个,元素从0开始
    cout<<ans<<endl;
    return 0;
}
相关文章
|
22天前
|
算法 索引
LeetCode(搜索插入位置)
如何使用二分查找算法来解决LeetCode上的“搜索插入位置”问题,确保时间复杂度为O(log n),并提供了详细的代码实现和分析。
14 2
|
3月前
|
算法
LeetCode第35题搜索插入位置
这篇文章介绍了LeetCode第35题"搜索插入位置"的解题方法,通过使用二分查找法,高效地找到在有序数组中插入一个目标数的最佳位置。
LeetCode第35题搜索插入位置
|
6月前
|
存储 机器学习/深度学习 算法
搜索(DFS与BFS):
搜索(DFS与BFS):
43 0
搜索(DFS与BFS):
|
6月前
|
C++ 索引 Python
leetcode-35:搜索插入位置
leetcode-35:搜索插入位置
33 0
|
算法 安全 Swift
LeetCode - #35 搜索插入位置
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
|
索引
leetcode:35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
42 0
|
机器学习/深度学习 数据采集 算法
搜索与图论-DFS
搜索与图论-DFS
|
Java C++ 索引
|
算法 索引
LeetCode:35. 搜索插入位置
题目描述:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。
|
定位技术