• dfs 学习笔记


    DFS算法是一一个递归算法,需要借助一个递归工作栈,故它的空问复杂度为O(V)。
    遍历图的过程实质上是对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用结构。
    邻接表表示时,查找所有顶点的邻接点所需时间为O(E),访问顶点的邻接点所花时间为O(V),此时,总的时间复杂度为O(V+E)。
    邻接矩阵表示时,查找每个顶点的邻接点所需时间为O(V),要查找整个矩阵,故总的时间度为O(V^2)。 
     v为图的顶点数,E为边数。

    1.搜索的数据结构基础 STL###

    a. 栈 stack
    Last in First out

     stack<int> s; //定义方法
    //基本操作
     s.push(x) //压栈
     s.pop();  //突出栈顶元素
     s.top(); //查询栈顶元素
    

    b. 队列 Queue
    First in First out

    Queue<int> Q; //定义队列
    //基本操作
    Q.push(x); // 进队
    Q.pop();   // 出队
    Q.front(); //查询队首元素
    Q.back();  //查询队尾元素
    Q.empty(); //查询队列是否为空
    Q.size();  //查询对内元素数量
    

    2.深度优先搜索dfs 例题###

    全排列

    用搜索找到全排列

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int a[20];
    int n;
    void dfs(int x);
    bool vis[20];
    int main(){
      cin>>n;
      dfs(1);
      return 0;
    }
    void dfs(int x){
      if(x==n+1){
        for(int i=1;i<=n;i++) cout<<a[i]<<" ";
        cout<<endl;
        return;
      }
      for(int i=1;i<=n;i++){
        if(!vis[i]){
          a[x]=i; 
          vis[i]=1;
          dfs(x+1);
          vis[i]=0;
        }
      }
    }
    

    选数游戏 luogu P1036

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,k,Ans;
    int p[30];
    bool CheckPri(int n){
      if(n==1||n==0) return false;
      if(n==2) return true;
      for(int i=2;i*i<=n;i++)
        if(n%i==0) return false;
      return true;
    }
    void dfs(int res,int pos,int sum){
      if(!res){
        Ans+=CheckPri(sum);
        return;
      }
      if(pos>n)return;
      dfs(res-1,pos+1,sum+p[pos]);
      dfs(res,pos+1,sum);
    }
    int main(){
      cin>>n>>k;
      for(int i=1;i<=n;i++) cin>>p[i];
      dfs(k,1,0);
      cout<<Ans<<endl;
      return 0;
    }
    

    一个更简单的选数例题 选自‘挑战程序设计竞赛’例题

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,k;
    int a[20];
    int Ans[20];
    bool vis[20];
    bool dfs(int x,int sum){
      if(x>n)return sum==k;
      if(dfs(x+1,sum))return true;
      if(dfs(x+1,sum+a[x]))return true;
      return false;
    }
      
    int main(){
      cin>>n>>k;
      for(int i=1;i<=n;i++) cin>>a[i];
      if(dfs(0,0)) cout<<"YES"<<endl;
      else cout<<"NO"<<endl;
      return 0;
    }
    

    Lake counting 最经典的搜索例题

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int x,y;
    char a[110][110];
    int Ans;
    void dfs(int n,int m){
      if(n<1||n>x)return;
      if(m<1||m>y)return;
      a[n][m]='.';
      for(int mx=-1;mx<=1;mx++){
        for(int my=-1;my<=1;my++){
          if(a[n+mx][m+my]=='W'&&(n+mx)>=1&&(n+mx)<=x&&(m+my)>=1&&(m+my)<=y)
        dfs(n+mx,m+my);
        }
      }
    }
    int main(){
      cin>>x>>y;
      for(int i=1;i<=x;i++)
        for(int j=1;j<=y;j++)
          cin>>a[i][j];
      for(int i=1;i<=x;i++){
        for(int j=1;j<=y;j++){
          if(a[i][j]=='W'){
        Ans++;
        dfs(i,j);
          }
        }
      }
      cout<<Ans<<endl;
      return 0;
      
    }
    

    HDUOJ p1010 temper of bone

    Dfs 奇偶性剪枝搜索

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int N,M,T;
    bool flag=0;
    char a[10][10];
    bool vis[10][10];
    int sx,sy,fx,fy;
    int ux[5]={0,0,1,-1};
    int uy[5]={1,-1,0,0};
    void dfs(int x,int y,int k){
      printf("i=%d j=%d
    ",x,y);
      if(flag)return;
      if(k<0) return;
      if(x<1||x>N)return;
      if(y<1||y>M)return;
      if(x==fx&&y==fy&&k==0){
        flag=1;
        return;
      }
      int dis=abs(x-fx)+abs(y-fy);
      if(k-dis<0)return;
      if((k-dis)%2) return;
      for(int i=0;i<4;i++){
        int px=x+ux[i],py=y+uy[i];
        if(a[px][py]!='X'&&!vis[px][py]){
          vis[px][py]=1;
          dfs(px,py,k-1);
          vis[px][py]=0;
        }
      }
    }
    int main(){
      while(1){
        cin>>N>>M>>T;
        if(N==0&&M==0&&T==0)break;
        memset(a,0,sizeof(a));
        memset(vis,0,sizeof(vis));
        flag=0;
        for(int i=1;i<=N;i++)
          for(int j=1;j<=M;j++){
        cin>>a[i][j];
        if(a[i][j]=='S') sx=i,sy=j;
        if(a[i][j]=='D') fx=i,fy=j;
          }
        vis[sx][sy]=1;
        dfs(sx,sy,T);
        if(flag)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
      }
      return 0;
    }
    

    Luogu P1135 奇怪的电梯

    暴力dfs但是需要避免死循环所以用vis数组标记

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int N,A,B,Ans=2147483647;
    bool flag;
    bool vis[210];
    int K[210];
    void dfs(int x,int tim){
      if(tim>Ans)return;
      if(x>N||x<1)return;
      if(x==B){
        flag=1;
        Ans=min(tim,Ans);
        return;
      }
      if(K[x]==0)return;
      if(x+K[x]<=N&&!vis[x+K[x]]){
        vis[x+K[x]]=1;
        dfs(x+K[x],tim+1);
        vis[x+K[x]]=0;
      }
      if(x-K[x]>=1&&!vis[x-K[x]]){
        vis[x-K[x]]=1;
        dfs(x-K[x],tim+1);
        vis[x-K[x]]=0;
      }
    }
        
    int main(){
      cin>>N>>A>>B;
      for(int i=1;i<=N;i++)cin>>K[i];
      dfs(A,0);
      if(flag)cout<<Ans<<endl;
      else cout<<-1<<endl;
      return 0;
    }
    

    Luogu P 1118 数字三角形

    模拟出规律+dfs暴力

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    int n,sum;
    int c[110][110],Ans[110];
    bool vis[110];
    void dfs(int num,int tot){
        if(tot>sum)return;
        if(num>n){
            if(tot==sum){
                for(int i=1;i<=n;i++)cout<<Ans[i]<<" ";
                exit(0);   //exit(0)表示结束当前函数进程,回归主函数
            }
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                vis[i]=1;
                Ans[num]=i;
                dfs(num+1,tot+i*c[n][num]);
                vis[i]=0;
            }
        }
    
    
    }
    int main(){
        cin>>n>>sum;
        c[0][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
                c[i][j]=c[i-1][j]+c[i-1][j-1];
        //law:用杨辉三角打出一个字表,字典序最小的需要满足sum{i*C[n][i]}
        dfs(1,0);
        return 0;
    }
    

    Luogu p1123 取数游戏

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int T,N,M;
    int a[10][10];
    int u[]={0,0,0,1,1,-1,-1,1,1},
        v[]={0,1,-1,0,0,1,-1,1,-1};
    int Ans=-1;
    int num[10][10];
    int dfs(int x,int y,int sum){
      if(y>M){
        x++;
        y=1;
      }
      if(x>N){
        Ans=max(Ans,sum);
        return Ans;
      }
      if(num[x][y]==0){
        for(int i=1;i<9;i++) num[x+u[i]][y+v[i]]++;
        dfs(x,y+2,sum+a[x][y]);
        for(int i=1;i<9;i++) num[x+u[i]][y+v[i]]--;
      }
      dfs(x,y+1,sum);
    }
    int main(){
      cin>>T;
      while(T--){
        cin>>N>>M;
        memset(a,0,sizeof(a));
        memset(num,0,sizeof(num));
        Ans=-1;
        for(int i=1;i<=N;i++)
          for(int j=1;j<=M;j++)
        cin>>a[i][j];
        dfs(1,1,0);
        cout<<Ans<<endl;
      }
      return 0;
    }
    
  • 相关阅读:
    面象对象设计原则之四:接口隔离原则(The Interface Segregation Principle,ISP)
    面象对象设计原则之三:里氏替换原则(The Liskov Substitution Principle,LSP)
    面象对象设计原则之二:开放封闭原则(Open-Closed Principle, OCP)
    面象对象设计原则之一:单一职责原则(Single Responsibility Principle, SRP)
    asp.net core 2.0中的配置(1)---Configuration
    UML类图与类的关系详解
    Javascript中的闭包和C#中的闭包
    Delphi考虑sql注入 QuotedStr
    delphi 窗体的创建和释放
    Delphi ADOQuery连接数据库的查询、插入、删除、修改
  • 原文地址:https://www.cnblogs.com/KingBenQi/p/12264731.html
Copyright © 2020-2023  润新知