裝貨物

  • 2020 年 2 月 13 日
  • 筆記

題目描述:

有 n 件貨物, 第 i 件重 ​Wi 噸,另有 x 個集裝箱,每個集裝箱可以裝重量不超過 W 噸的貨物。

貨物不能分拆,請判斷這 x 個集裝箱能否裝下所有貨物。

輸入描述:

第一行一個整數 T ,表示數據組數。對於每組數據:第一行三個整數 n,x,W。第二行 n 個整數,第 i 個表示 Wi。

保證 1≤T≤

,1≤n≤21,1≤x,Wi

,W≤

, n>10的數據不會超過 2 組。

輸出描述:

對於每組數據輸出一行一個字元串,能裝下所有貨物輸出 Yes ,否則輸出 No 。

輸入樣例:

2  5 2 20  2 4 6 8 10  1 114514 1919810  114514

輸出樣例:

Yes  Yes

說明:

樣例數據的一種可能方案:{4,6}, {2,8,10} 。

題目鏈接:https://ac.nowcoder.com/acm/contest/3781/C

解題思路:

自閉ing,我一開始以為這題是用貪心演算法:總共x個集裝箱 先把貨物往第一個集裝箱裝,能裝下就繼續放下一個貨物,不能裝下就看第二 三… x個集裝箱能不能,要是n件貨物能全部裝下就輸出Yes否則輸出No。 一提交直接WA,正確的思路應該是深度優先遍歷+回溯法。先把所有的貨物根據重量降序排列,然後從第一個貨物開始用dfs,遍歷u個集裝箱看哪個箱子能放下當前貨物(u為當前正在裝載的貨物個數),當集裝箱能放下該貨物時就開始遍歷下一個貨物,直到裝載完n個貨物為止return true輸出Yes,否則輸出No。

AC程式碼:

#include <bits/stdc++.h>  using namespace std;  #define Up(i,a,b) for(int i = a; i <= b; i++)  #define ms(a,x) memset(a,x,sizeof(a))  const int maxn = 101;    int n,x,W;    //貨物數n,集裝箱個數x,集裝箱最多載重W  int w[maxn];    //w[i]表示第i件貨物的重量  int box[maxn];  //box[i]表示第i集裝箱當前裝載的重量    bool dfs(int u)   //u表示當前在裝載第u個貨物  {      if(u > n) return true;      for(int i = 1; i<=u && i<=x; i++)   //看往哪個集裝箱裝,一定要i<=u不然會超時      {          if(box[i]+w[u] <= W)          {              box[i] += w[u];              if(dfs(u+1)) return true;              box[i] -= w[u];          }      }      return false;  }    int main()  {      ios::sync_with_stdio(false);      cin.tie(0), cout.tie(0);      int t;      cin >> t;      while(t--)      {          cin >> n >> x >> W;          ms(w,0),ms(box,0);   //初始化          Up(i,1,n)          {              cin >> w[i];          }          sort(w+1,w+1+n,greater<int>());  //降序排列          cout << (dfs(1) ? "Yes" : "No") << endl;      }      return 0;  }