NKOJ4837[PA2014]Pakowanie 状压dp
[PA2014]Pakowanie
题面:你有n个物品和m个包。物品有重量且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?
解法:朴素的状压dp,但是发现无法转移,于是增加一个状态g[s]表示状态为s是最后一个背包的容量即可转移。注:时限4s,能过
#include <bits/stdc++.h> using namespace std; int a[(1 << 24) + 1], c[(1 << 24) + 1], f[(1 << 24) + 1], g[(1 << 24) + 1]; int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[1 << (i - 1)]); for (int i = 1; i <= m; i++) scanf("%d", &c[i]); sort(c + 1, c + m + 1, greater<int>()); int tot = (1 << n) - 1; for (int s = 1, i, j, s0; s <= tot; s++) { f[s] = 0x3f3f3f3f;g[s] = -f[s]; for (j = s; j; j ^= i) { i = j & -j; s0 = s ^ i; if (a[i] <= g[s0]) { if (f[s0] < f[s] || (f[s0] == f[s] && g[s0] - a[i] > g[s])) { f[s] = f[s0]; g[s] = g[s0] - a[i]; } } else { if (f[s0] >= m || c[f[s0] + 1] < a[i]) { continue; } if (f[s0] + 1 < f[s] || (f[s0] + 1 == f[s] && (c[f[s0] + 1] - a[i]) > g[s])) { f[s] = f[s0] + 1; g[s] = c[f[s0] + 1] - a[i]; } } } } f[tot] <= m ? printf("%d", f[tot]) : puts("NIE"); }

浙公网安备 33010602011771号