DFS
深度优先搜索,类似于树的先序遍历
(第一次学DFS是在图中遇到的,那就先回顾下图里的DFS)
代码(以邻接表为例)
基于邻接表的复杂度为O(n+e),而基于邻接矩阵要O(n方)
void DFS_Visit(Graph &G)
{
for(int i=0;i<G.vexnum;i++)
{
visit[i]=false;//初始化
}
for(int i=0;i<G.vexnum;i++)
{
if(visit[i]==false)
{
DFS(G,i);
}
}
//如果图有多个连通分量,就需要多个节点分别起始DFS
}
void DFS(Graph &G,int index)
{
ArcNode *p;
visit[index]=True;
//每个节点遍历一次就好了
p=G->VexNode[index].firstarc;
while(p)
{
if(visit[p->adjvex]==false)
{
DFS(G,p->adjvex);
}
p=p->nextarc;
}
}
DFS做全n个数排列
int main()
{
DFS(0);
return 0;
}
void DFS(int index)
{
if(index==n)
{
for(int i=0;i<n;i++)
{
cout<<a[i];
}
return ;
}
for(int i=0;i<n;i++)
{
if(vis[i]==0)
{
vid[i]=1;
a[depth]=i;
DFS(depth+1);
vis[i]=0;
}
}
}
例题
给定n个正整数,判断是否可以从中选取若干个正整数,使他们的和恰为整数k
include<bits/stdc++.h>
using namespace std;
int k;
bool DFS(int index,int sum)
{
if(sum==k)
{
return true;
}
//要a[index]
if(DFS(index+1,sum+a[index])==true)
return true;
//不要a[index]
if(DFS(index+1,sum)==true)
return true;
return false;
}
int main()
{
int n;
cin>>n>>k;
int *a=(int *)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
{
cin>>a[i];
}
if(DFS(0,0)==true)
{
cout<<"YES";
}
else
cout<<"NO";
return 0;
}
Lake Counting
#include<bits/stdc++.h>
using namespace std;
int **N;
char **G;
int dx[8]={0,1,1,1,0,-1,-1,-1};
int dy[8]={1,1,0,-1,-1,-1,0,1};
int n,m;
void DFS(int x,int y)
{
N[x][y]=1;
int nx,ny;
for(int i=0;i<8;i++)
{
nx=x+dx[i];
ny=y+dy[i];
if(nx>=0 && nx<n && ny>=0 && ny<m &&N[nx][ny]==0&&G[nx][ny]=='W')
{
DFS(nx,ny);
}
}
}
int main()
{
cin>>n>>m;
G=(char **)malloc(sizeof(char *)*n);
N=(int **)malloc(sizeof(int *)*n);
for(int i=0;i<n;i++)
{
G[i]=(char *)malloc(sizeof(char)*m);
N[i]=(int *)malloc(sizeof(int)*m);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>G[i][j];
N[i][j]=0;
}
}
int flag=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(N[i][j]==0&&G[i][j]=='W')
{
DFS(i,j);
flag++;
}
}
}
cout<<flag;
}
BFS
广度优先搜索,类似于树的层次遍历
代码
void BFS_visit(Graph &G)
{
for(int i=0;i<G.vexnum;i++)
{
visit[i]=false;//初始化
}
for(int i=0;i<G.vexnum;i++)
{
if(visit[i]==false)
{
BFS(G,i);
}
}
//如果图有多个连通分量,就需要多个节点分别起始BFS
}
void BFS(Graph G,int index)
{
ArcNode *p;
int Qu[MAX_V],front=rear=0;
Qu[rear++]=index;//先赋值rear再自动加一,起始点入队
visit[index]=true;
while(front!=rear)
{
i=Qu[front];
front=(front+1)%MAX_V;
cout<<G.vex[i];
p=G->VexNode[i].firstarc;
while(p)
{
if(visit[p->adjex]==false)
{
Qu[rear]=p->adjex;
rear=(rear+1)%MAX_V;
visit[p->adjex]=true;
}
p=p->nextarc;
}
}
}
BFS找迷宫入口到出口的最短路径
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<N;j++)
{
cin>>s[i][j];
if(s[i][j]=='S')
{
Sx=i;
Sy=j;
step[i][j]=0;
//起点
}
step[i][j]=-1;
}
}
queque<node> q;
//get到一种初始化node的方法
q.push(node{Sx,Su});
int ans=-1;
while(q.size()>0)
{
int x=q.front().x;
int y=q.front().y;
q.pop();
for(int i=0;i<4;i++)
{
int newx=x+dx[i];
int newy=y+dy[i];
if(newx>0 && newx<n &&newy>0 && newy<m &&step[newx][newy]=-1 &&s[newx][newy]!='#' )
{
//这种累加的形式可以记录长度ei
step[newx][newy]=step[x][y]+1;
if(s[newx][newy]=='G')
{
ans=step[newx][newy];
break;
}
q.push(node{newx,newy});
}
}
if(ans!=-1)break;
}
cout<<ans;
}
记忆化搜素
在搜索过程中会有很多重复计算,故可以记录下来一些结果(空间换时间)
举例:斐波那契数列
int fib(int n)
{
//dp初始化全部为-1
if(dp[n]!=-1)return dp[n];
if(n==0||n==1)return dp[n]=1;
return dp[n]=fib(n-1)+fib(n-2);
}
C++补充知识
c++中,内存分为5个区,分别为栈,堆,自由存储区,全局/静态存储区,常量存储区
各种变量
(后两行写反了)
栈
由编译器在需要时分配,不需要时自动清除的变量的存储区,通常为局部变量,函数参数等。
堆
由new分配的内存块,由程序控制其释放,如果程序没有释放,程序结束后,操作系统会自动回收。
自由存储区
由malloc等分配的内存块,和堆相似
全局、静态存储区
全局变量和静态变量被分配到同一块内存中
常量存储区
存放常量
例子
void ex()
{
int* p=new int[5];
}
该函数在栈中存放了一个指向堆内存的指针p。