CSUST摸鱼的tomjobs(dfs+剪枝+贪心)

题目连接:

摸鱼的tomjobs

题意:

抽象来说就是一堆物品,背包容量有限,如何用最少的背包将这些物品装在背包中,之前在ACwing学剪枝时写过类似的题目,更好的认识剪枝

思路分析:

n的数据范围很小,可以直接考虑暴力的思路,处理每个物品的选择就两种,要么放在之前的背包中(前提是能放下),要么新开一个背包,所以dfs时存的状态为:

当前正在考虑哪个物品,当前已经开的最小背包数,即dfs(int cur,int cnt)这里就是最优剪枝的思维,用全局res记录答案,如果当前cnt已经大于res,下面

所有的方案都不是最优的,直接return,还有考虑物品的顺序可以贪心的取从大到小,因为先把大的物品放进背包后之后的搜索空间会减小。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=20;
int c[N];
int b[N];
int n,w;
int res;
void dfs(int cur,int cnt)
{
    if(cnt>=res) return;
    //最优剪枝
    if(cur==n+1){
        res=min(res,cnt);
        return;
    }
    //考虑放进之前的背包中
    for(int i=1;i<=cnt;i++){
        if(b[i]+c[cur]<=w){
            b[i]+=c[cur];
            dfs(cur+1,cnt);
            b[i]-=c[cur];//回溯
        }
    }
    //新开一个背包
    b[cnt+1]+=c[cur];
    dfs(cur+1,cnt+1);
    b[cnt+1]-=c[cur];//回溯
}
int main()
{
    cin>>n>>w;
    for(int i=1;i<=n;i++)
        scanf("%d",&c[i]);
    sort(c+1,c+n+1);
    reverse(c+1,c+n+1);//贪心考虑
    res=n;
    dfs(1,1);
    cout<<res<<endl;
    return 0;
}

posted @ 2020-11-21 20:46  Taoger_Xu  阅读(87)  评论(0)    收藏  举报