题面
题解
剪枝分类
dfs优化主要分成5类
1、优化搜索顺序(大部分情况下,我们应该优先搜索分支较少的结点)
2、排除等效冗余
3、可行性剪枝
4、最优性剪枝
5、记忆化搜索
做法
依次遍历所有的猫,通过第u只猫往现有的第k个辆车中放来遍历所有情况,(可以放入第 i 辆车,也可以新开一辆车放入)
优化
优先放重的猫,优化搜索顺序,因为先放重的,可以减少接下来的分支,使遍历情况减少
当前猫放入已经超出最大限制,就不再进行遍历,可行性剪枝
新开车的数量大于答案的值,接下来肯定不是答案,最优化剪枝
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=20;
ll n,m;
ll ans=N;
ll w[N];
ll sum[N];
void dfs(int u,int k){
//最优性剪枝
if(k>=ans) return;
if(u==n){
ans=k;
return ;
}
for(int i=0;i<k;i++){ //枚举第u个物品应该放在哪辆车上
if(sum[i]+w[u]<=m){ //可行性剪枝
sum[i]+=w[u];
dfs(u+1,k);
sum[i]-=w[u]; //恢复现场
}
}
//新开一辆车
sum[k]=w[u];
dfs(u+1,k+1);
sum[k]=0;//恢复现场
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>w[i];
sort(w,w+n); //优化搜索顺序
reverse(w,w+n);
dfs(0,0); //从0号点,第0辆车开始
cout<<ans<<endl;
return 0;
}