题目

件货物, 第 件重 吨,另有 个集装箱,每个集装箱可以装重量不超过 吨的货物。
货物不能分拆,请判断这 个集装箱能否装下所有货物。

解题思路

  • 先确定最重的货物重量 ,如果 ,因为货物不能分拆,所以这些集装箱不能装下这个货物。

  • 再比较 ,如果 ,那么每个货物都可以单独放置一个集装箱,所以答案是 Yes。

  • 如果 ,使用回溯算法。

表示第 个集装箱当前装下货物的重量。

回溯算法:
试着将第 个货物放到第 个集装箱中,如果可以装下,就装进去,,然后装第 个货物。
如果装完了所有货物,就返回 true。
如果上述方案失败,就返回前一步,重置成之前的状态,,将第 个货物放到第 个集装箱中。重复上述步骤。
如果试完了所有集装箱,而货物还没装完,返回 false。

装第 个货物时,可以只考虑前 个箱子,假如使用了 个箱子,至少会出现一个空箱子。

C++代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<int> w, a;
int n, x, W;

bool dfs(int k){
    if(k==n)
        return true;
    for(int i=0; i<min(k+1,x); ++i){
        if(a[i]+w[k]<=W){
            a[i]+=w[k];
            if(dfs(k+1))
                return true;
            a[i]-=w[k];
        }
    }
    return false;
}

int main(){
    int T;
    cin >> T;
    while(T--){
        cin >> n >> x >> W;
        w.resize(n);
        int ma = 0;
        for(int i=0; i<n; ++i){
            cin >> w[i];
            ma = max(ma, w[i]);
        }
        if(ma>W){
            cout << "No" << endl;
            continue;
        }
        if(n<=x){
            cout << "Yes" << endl;
            continue;
        }

        a.resize(x,0);
        for(int i=0; i<x; ++i) a[i]=0;

        if(dfs(0))
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}