【最优性剪枝 子树大小剪枝】 小猫爬山
传送门
题意
运送\(n\)个猫下山,每个车上最多承受\(w\)重量,\(n\)只小猫的重量分别为\(c_{1},c_{2},\dots ,c_{n}\)。
每用一辆车需要\(1\)元,求最少可以花多少钱将所有猫送下山
数据范围
\(1\leq N \leq 18\)
\(1\leq C_{i}\leq W\leq 10^{8}\)
题解
\(n\)范围较小,可以直接暴搜,
两个状态,\(u\)记录当前是第几只猫,\(cnt\)表示当前装了几辆车
搜索时要搜索以每个猫单独在一辆车里面的情况,然后一次将其它猫装入当前车
两个剪枝优化。
- 如果当前的车的数目已经大于已经得到数目最小值可以终止
- 搜索车的重量的时候,先将重量重的放入可以减少搜索树分支的数量
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
const int N=20;
int car[N],c[N];
int n,w;
int ans;
void dfs(int u,int cnt)
{
if(cnt >= ans) return;
if(u==n+1)
{
ans=min(ans,cnt);
return;
}
rep(i,1,cnt+1)
{
if(car[i]+c[u]<=w)
{
car[i]+=c[u];
dfs(u+1,cnt);
car[i]-=c[u];
}
}
car[cnt+1]=c[u];
dfs(u+1,cnt+1);
car[cnt+1]=0;
}
int main()
{
cin>>n>>w;
rep(i,1,n+1) cin>>c[i];
sort(c+1,c+1+n);
reverse(c+1,c+1+n);
ans=n;
dfs(1,0);
cout<<ans<<endl;
}