CSUST摸魚的tomjobs(dfs+剪枝+貪心)
阿新 • • 發佈:2020-11-21
題目連線:
題意:
抽象來說就是一堆物品,揹包容量有限,如何用最少的揹包將這些物品裝在揹包中,之前在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; }