题目
思路
- 暴搜顺序:从前往后依次枚举每只小猫,枚举当前这只小猫应该放在哪一辆车上,递归完n层之后,就可以知道所有方案中的最少车辆总数
- 剪枝的情况:
- 优化搜索顺序:大部分情况下,应该优先搜索分支较少的节点
- 排除等效冗余
- 可行性剪枝
- 最优性剪枝
- 记忆化搜索(DP)
- 本题的剪枝:
- 优化搜索顺序:优先放重猫
- 可行性剪枝:如果放入当前的猫,车的重量超出,则舍弃该方案
- 最优性剪枝:如果当前车的数量已经大于等于ans(符合条件的最少车的数量)
代码
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=20;
int n,m;
int w[N];
int sum[N]; //当前猫的重量
int ans=N;
void dfs(int u,int k){ // u:当前猫的数量,k:当前车的数量
//最优性剪枝
if(k>=ans)return ; //当前车的数量大于等于ans
if(u==n){
ans=k;
return;
}
//枚举当前这只猫可以放到哪辆车上去
for(int i=0;i<k;i++){
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);
cout<<ans<<endl;
return 0;
}