在开始之前,我们要先了解深度优先搜索的基本知识。
DFS(深度优先搜索)能解决哪些问题?
一般来说,DFS用于暴搜,连通性问题,求解符合条件的方案数,最大值,最小值等问题。
DFS的要素
一般来说,DFS具有下列要素:
1,终止条件。所有的递归类解法都有一条递归边界,也就是我们这里的终止条件。
2,减枝。什么叫减枝呢?我们知道很多时候,我们在递归的时候,由于条件限制比较少,数据分布比较不合理等问题,导致我们往往会进行大量无意义的计算。比如我们在输出数组中最大值的时候,我们倘若事先知道该数组是由从大到小排列的话,我们只需要直接输出数组的最后一位就可以了,并不需要依次遍历。而减枝类似,我们优先遍历分支较少的节点,或者当我们达到某一个条件的时候,我们放弃遍历下面的节点,这就是减枝的操作。
3,递归搜索下一层。
4,保护现场和恢复现场。这里的作用是让我们能够重复访问该节点,且保证节点的数据内容不变。
小猫下山问题
我们来看题干:
本题要求最少要多少辆车,符合我们深度优先搜索能解决问题的范畴。我们开始解题,首先我们要确定深度优先搜索函数的每个节点的参数。很显然,我们每个节点的参数是当前所用的车辆数和当前处理的猫猫数。
那么,我们的终止条件就是,当我们的猫猫数等于n的时候,输出当前的车辆数,该车辆数就是我们的答案。我们设置变量ans来记录我们的答案。我们赋值变量ans的初始值的时候要赋值大一些,这样我们才能往下求其最小值。题目要求最少的车辆数,那么也就是说,一旦我们的车辆数大于当前ans的时候,我们便可以放弃求接下来的节点,直接return即可。
我们坐车的情况有两种,也就是我们有两种情况可进入下一节点。第一种情况,我们当前的车可以容纳下一只猫猫,那么我们就进入下一节点,为猫猫数加1,车不变。第二种情况,我们当前的车不能容纳下一只猫猫,那么我们就要把那只猫猫单独放到一个车子里,再新买一个车,下一节点为车加1,猫猫也加1。
接下来看代码实现:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int catw[20],carw[20];
int ans=20;
int n,w;
void dfs(int cat,int car){
if(car>=ans){//减枝
return;//检验
}
if(cat==n){
ans=car;
return;
}
for(int i=0;i<car;i++){
if(carw[i]+catw[cat]<=w){
carw[i]+=catw[cat];
dfs(cat+1,car);
carw[i]-=catw[cat];
}
}
carw[car]=catw[cat];
dfs(cat+1,car+1);
carw[car]=0;
}
int main(){
cin>>n>>w;
for(int i=0;i<n;i++){
cin>>catw[i];
}
sort(catw,catw+n);//减枝
reverse(catw,catw+n);//胖猫优先上车
dfs(0,0);
cout<<ans<<endl;
return 0;
}
注意这里的胖猫优先,我们先把我们的数据处理一下,按猫重量的从大到小排列,优先处理胖猫,因为胖猫的选择分支较少,优先处理能减少系统的计算时间。