Bzoj P3717 [PA2014]Pakowanie___狀壓dp
阿新 • • 發佈:2018-12-20
題目大意:
你有個物品,體積分別為 你也有個包,容量分別為 物品不可被分割,一個包可以放多個物品,問把所有物品裝入包中,至少需要幾個包?
分析:
顯然對於個物品,最壞的情況就是一個物品放進一個包,那麼我們只需要保留最大的個包 然後我們發現因為,所以可以想到用狀壓dp 設表示選了的物品狀態為時需要用到的最少的包的數量 然後設表示在用到的最少的包的數量為時,這些包中還能接受的最大體積,即最大揹包剩餘容積 轉移顯然
程式碼:
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <cstring> #include <cstdlib> #include <algorithm> #define inf 0x3f3f3f3f #define N 24 using namespace std; int f[(1<<N)+5], g[(1<<N)+5], B[N*5+5], A[N+5], n, m; bool cmp(int aa, int bb) { return aa > bb; } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &A[i]); for (int i = 1; i <= m; i++) scanf("%d", &B[i]); sort(B + 1, B + m + 1, cmp); int MaxNum = (1 << n) - 1; for (int i = 1; i <= MaxNum; i++) f[i] = inf; for (int i = 1; i <= MaxNum; i++) for (int j = 1; j <= n; j++) if ((i >> (j - 1)) & 1) { int k = i & (~(1 << (j - 1))); if (g[k] >= A[j]) { if (f[i] > f[k] || (f[k] == f[i] && g[k] - A[j] > g[i])) f[i] = f[k], g[i] = g[k] - A[j]; } else if (B[f[k] + 1] >= A[j]) { if (f[i] > f[k] + 1 || (f[k] + 1 == f[i] && B[f[k] + 1] - A[j] > g[i])) f[i] = f[k] + 1, g[i] = B[f[k] + 1] - A[j]; } } if (f[MaxNum] == inf) printf("NIE"); else printf("%d",f[MaxNum]); return 0; }