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\n",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;
}
posted @ 2020-02-05 17:52  KingBenQi  阅读(168)  评论(0编辑  收藏  举报