【最优性剪枝 子树大小剪枝】 小猫爬山

传送门

题意

运送\(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;
}
posted @ 2020-10-10 13:44  Hyx'  阅读(131)  评论(0编辑  收藏  举报