文章目录
一、DFS是什么?
dfs是指深度优先搜索。从我的理解来说,就是从一个节点出发,一直往下走,走到无法继续的时候,再返回上一层,继续尝试;直到走完所有情况,或者找到满足条件的。
二、BFS是什么?
bsf是指宽度优先搜索。从我的理解来说,就是从一个节点出发,一步步地走从该节点出发,实现所有的可能性。
三、BFS和DFS的区别
在以前学信息学竞赛的时候,我们老师曾这么这么解释:bfs就是从一个点出发,一直走到底,竖着一列列搜索;dfs就是从一个点出发,走所有可能的地方,横着一层层搜索。
四、需要注意的点
搜索完当前点,回溯的时候,要注意还原原来的状态。例如在取书问题中,我们可以用一个数组标记哪些书已经取过,在回溯的时候,记得要将该书重新标记回未取过。
基本模板:
int check(参数)
{
if(满足条件)
return 1;
return 0;
}
void dfs(int step)
{
判断边界
{
相应操作
}
尝试每一种可能
{
满足check条件
标记
继续下一步dfs(step+1)
恢复初始状态(回溯的时候要用到)
}
}
五、二分是什么?
二分最经典的案例,便是猜数游戏,每次猜当前范围的中值,是猜到目标值的最优方法。二分思想便是设置边界,将中值与目标想相比较;然后转换边界,以中值为界限,转换为左边界或右边界。
下面这个是一个师兄推荐的,也是我最喜欢的一个模板
int l = 下界 - 1 r = 上界 + 1
while (l+1 <r) {
int mid = (l+r) >> 1;
if (c(mid)) l = mid; else r = mid;
}
//l 为满足 c(x) 的最大值, r为不满足c(x)的最小值
六、专题题解
1. Lake Counting
题意:给出n*m方格,求有多少个被“.”包围的“w”区域
思路:经典dfs题,搜索一下。
#include <iostream>
#include <string>
using namespace std;
string s[110];
int a[8][2]={{0,1},{0,-1},{1,0},{1,-1},{1,1},{-1,0},{-1,1},{-1,-1}};
int n,m;
bool check(int x,int y)
{
if (s[x][y]=='W') return 1;
else return 0;
}
void dfs(int x,int y)
{
if (check(x,y))
{
s[x][y]='.';
for (int i=0;i<8;i++)
{
int x1,y1;
x1=x+a[i][0];
y1=y+a[i][1];
if ((x1>=0)&&(x1<n)&&(y1>=0)&&(y1<m))
dfs(x1,y1);
}
return;
}else
return;
}
int main()
{
cin>>n>>m;
int i,j,ans=0;
for (i=0; i<n; i++)
{
cin>>s[i];
}
for (i=0; i<n; i++)
for (j=0; j<m; j++)
{
if (check(i,j))
{
dfs(i,j);
ans++;
}
}
cout <<ans<<endl;
return 0;
}
2.Red and Black
题意:给出n*m方格,求从“@”出发,不碰及“#”边界,可以走到的“.”有多少个?
思路:与上题相似,先找到“@”点,从该点出发深搜。
#include <iostream>
int n,m,ans;
using namespace std;
char s[30][30];
int ss[30][30];
int a[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
bool check(int x,int y)
{
if (s[x][y]!='#'&&ss[x][y]==0&&x>=0&&x<n&&y>=0&&y<m)
return 1;
else
return 0;
}
void dfs(int x,int y)
{
if (check(x,y))
{
ans++;
ss[x][y]=1;
for (int i=0; i<4; i++)
{
int x1,y1;
x1=x+a[i][0];
y1=y+a[i][1];
dfs(x1,y1);
}
}
else
return;
}
int main()
{
while (1)
{
cin>>m>>n;
if (n==0&&m==0)
break;
int i,j,x,y;
ans=0;
for (i=0; i<n; i++)
{
for (j=0; j<m; j++)
{
cin>>s[i][j];
ss[i][j]=0;
if (s[i][j]=='@')
{
x=i;
y=j;
}
}
}
dfs(x,y);
cout<<ans<<endl;
}
return 0;
}
3. Accepted Necklace
题意:实际为01背包
思路:可以用dp,这里锻炼一下dfs。dfs过程中记录一下所用石子数量,所用石子价值,所用石子重量,再判断一下结束边界即可。
#include <iostream>
#include <string.h>
using namespace std;
struct shi
{
int a;
int b;
} shi[110];
int n,ans,k,wmax;
int v[110];
void dfs(int x,int w,int y,int dex)
{
if (w==wmax||x==k)
{
if (ans<y)
ans=y;
}
else if (w<wmax&&x<k)
{
for (int i=dex; i<n; i++)
{
if (v[i]==0&&(x+1)<=k&&(w+shi[i].b)<=wmax)
{
v[i]=1;
dfs(x+1,w+shi[i].b,y+shi[i].a,i+1);
v[i]=0;
}
}
}
}
int main()
{
int t;
cin>>t;
while (t--)
{
memset(v,0,sizeof(v));
cin>>n>>k;
int i;
ans=0;
for (i=0; i<n; i++)
cin>>shi[i].a>>shi[i].b;
cin>>wmax;
dfs(0,0,0,0);
cout<<ans<<endl;
}
return 0;
}