dfs-深度优先搜索(Depth-First-Search)
进入ACM实验室以来,这是老师传授给我们的第一个知识点。我认为,dfs就是遍历全部。可是我发现我完全不会,因为dfs并不是for循环遍历。dfs其实是一种回溯。回溯的概念,用一张图片来解释。
这是一株美丽的二叉树。
明白了这个思路,咱们就可以想出一种方法来遍历所有的最后的节点。
了解复杂度的肯定都知道。如果节点一多的话,直接遍历是不行的,所以我们发明了一种方法叫剪枝。
现在进行AC时刻
举个栗子。就用最经典的暴力背包吧;
题目描述
有一个背包,容积是30,有三样东西价值和体积分别为45,16 25,15 25,15试问,采取怎样的方法才可以把可以装进背包的物品的价值提升到最大。
二话不说直接上代码
#include<bits/stdc++.h>
using namespace std;
int w[]= {16,15,15},v[]= {45,25,25};
int tempw,tempv,totv;
int maxn=0;
void dfs(int t)
{
if(t==3) {
if(tempv>maxn&&tempw<=30)
maxn=tempv;
return ;
}
tempw+=w[t];
tempv+=v[t];
totv-=v[t];
if(tempw<=30&&tempv+totv>maxn)
dfs(t+1);
tempw-=w[t];
tempv-=v[t];
// totv+=v[t];
// totv-=v[t];
if(tempv+totv>maxn)
dfs(t+1);
totv+=v[t];
}
int main()
{
for(int i=0; i<3; i++)
totv+=v[i];
dfs(0);
cout<<maxn<<endl;
}
如果我没猜错,没学会dfs的人一定看的一脸懵逼。所以我把我理解步骤一点点的呈现出来。
首先得理解一下思路。
思路就是这个东西放还是不放。
所以代码走起
#include<bits/stdc++.h>
using namespace std;
int w[]= {16,15,15},v[]= {45,25,25};
int main()
{
dfs(0);\\直接访问第零层;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int w[]= {16,15,15},v[]= {45,25,25};int tempw,tempv;
int maxn=0;
dfs(int t){
if(t==3)//3的意思是你背包里的东西,也就是你的树的深度;因为有三个物体,你只有012这三层,
//等你读取第2层之后理所当然的走到了第3层,也就是判断层。
{
if(tempv>maxn&&tempw<=30)//处理maxn可交换条件
maxn=tempv;
return ;
}
}
int main()
{
dfs(0);\\直接访问第零层;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int w[]= {16,15,15},v[]= {45,25,25};
int tempw,tempv,totv;
int maxn=0;
dfs(int t)
{
if(t==3)
{
if(tempv>maxn&&tempw<=30)
maxn=tempv;
return ;
}//此时我就想往背包里填东西了,现在就说判断这个东西放不放的时候到了
//放
tempw+=w[t];
tempv+=v[t];
totv-=v[t];
if(tempw<=30&&tempv+totv>maxn)//同时想到如果你把所有的东西都放进去
//都不如你最大的价值大那么这个东西就不用放了;
//(因此引用totv,一开始就是全部的总价值,每一次丢弃都会把总价值改变)
dfs(t+1);//现在就是放了,放了的后续还有很多,留给以后;
//如果你不想放你后悔了,你是不是得拿出来呢?
tempw-=w[t];
tempv-=v[t];
totv+=v[t];//这样就拿出来了
//然后就说这个东西我不放的情况
totv-=v[t];
if(tempv+totv>maxn)
dfs(t+1);
totv+=v[t];//因为你只是试试,并不是真的就放了,所以你得放进去再拿回来。
}
int main()
{
dfs(0);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int w[]= {16,15,15},v[]= {45,25,25};
int tempw,tempv,totv;
int maxn=0;
void dfs(int t)
{
if(t==3) {
if(tempv>maxn&&tempw<=30)
maxn=tempv;
return ;
}
tempw+=w[t];
tempv+=v[t];
totv-=v[t];
if(tempw<=30&&tempv+totv>maxn)
dfs(t+1);
tempw-=w[t];
tempv-=v[t];
// totv+=v[t];你会发现一放一拿正好抵消了,所以就可以不写,但是为了理解还是写了
// totv-=v[t];
if(tempv+totv>maxn)
dfs(t+1);
totv+=v[t];
}
int main()
{
for(int i=0; i<3; i++)
totv+=v[i];
dfs(0);
cout<<maxn<<endl;
}
最终这个暴力背包就解决了。
跑一下程序
这个暴力背包整理OVER!
鸣谢Mr.Zhang
By-轮月