CSUST摸鱼的tomjobs(dfs+剪枝+贪心)
题目连接:
题意:
抽象来说就是一堆物品,背包容量有限,如何用最少的背包将这些物品装在背包中,之前在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;
}

浙公网安备 33010602011771号