1. 程式人生 > 實用技巧 >CSUST摸魚的tomjobs(dfs+剪枝+貪心)

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;
}