读书笔记
前言
当时学DFS和BFS做到一点笔记.再记录一次
(1)DFS一般不能保证找到最优解
(2)BFS:如果问题有解,一定能找到最优解
下面开始读书笔记
DFS
第一次学DFS的时候是学习怎么走迷宫,但是书上给了另一种看法:迷宫是图(数据结构),可以转换为树(应该是最小生成树)。如果用走迷宫的想法,即是当你遇到分岔口时,你可以选择的分支走(就像树的父亲节点和儿子节点的分支)。而遇到死路,就像到了叶子节点.
当然重点并不在这,书上介绍了背包问题,介绍了用DFS的眼光去看这个问题:
对于每一个物品,有两种选择,选或者不选,这就像遇到了分岔口。当所有物体都处理完毕后,就是到了叶子节点.
因为有背包容量这个限制条件,所以每次选择一个新物体的时候,如果选择的物体总重超过了背包容量,就不应该进入选择物体的分岔口了。,这就是剪枝
BFS
书中给了一个模板:
void BFS(int s){
queue<int> q;
q.push(s);
while(!q.empty()){
取出队首元素TOP;
访问队首元素TOP;
将队首元素出队;
将top下一层节点中未曾入队的节点全部入队.
}
}
书上给了一个例题,现在也写入读书笔记吧
给出一个
M∗N
M
∗
N
的矩阵,矩阵中的元素为0或1.称位置(x,y)与其上下左右四个位置(x,y+1),(x,y-1),(x+1,y),(x-1,y)是相邻的。如果矩阵中有若干个1是相邻的,那么称这些1构成了一个块,求给定矩阵中块的个数
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0
这个问题求解的基本思路是:枚举每一个元素,如果是0,跳过,如果是1,则使用BFS查询与该位置相邻的4个位置,判断它们是否为。而防止走回头路,一般可以设置一个bool型数组inq来记录每一个已经走过的路。
little trick:可以使用两个增量数组来表示4个方向
int X[] ={0,0,1,-1}; //下,上,右,左
int Y[] ={1,-1,0,0};
for(int i=0;i<4;i++){
newX = nowX+X[i];
newY = nowY+Y[i];
}
code
//matrix 是输入的矩阵
struct node{
int x,y;
}Node;
bool inq[M][N]={false};
int X[] ={0,0,1,-1}; //下,上,右,左
int Y[] ={1,-1,0,0};
bool judge(int x,int y){
if(x>=n ||x<0 || y>=m || y<0) return false;
if(matrix[x][y] ==0 || inq[x][y] ==true) return false;
return true;
}
void BFS(int x,int y){
queue<int> q;
Node.x=x,Node.y=y;
q.push(Node);
inq[x][y] =true;
while(!q.empty()){
node top = q.top();
q.pop();
for(int i=0;i<4;i++){
int newX =top.x+X[i];
int newY =top.y+Y[i];
if(judge(newX,newY)){
Node.x = newX;
Node.y = newY;
q.push(Node);
inq[newX][newY]=true;
}
}
}
}
int main()
{
//do input
int count=0;
for(int x=0;x<M;x++)
for(int y=0;y<N;y++)
if(matrix[x][y] ==1 && inq[x][y]==false){
count++;
BFS(x,y);
}
}