#include <algorithm>
#include <cassert>
#include <iostream>
using namespace std;
namespace {
unsigned make(unsigned a, unsigned b)
{
return (a << 27) | b;
}
unsigned get_first(unsigned p)
{
return p >> 27;
}
unsigned get_second(unsigned p)
{
return p & ((1U << 27) - 1);
}
int solve(vector<unsigned> items, vector<unsigned> packs)
{
sort(items.begin(), items.end());
sort(packs.begin(), packs.end(), greater<unsigned>());
if (packs.size() > items.size()) {
packs.resize(items.size());
}
while (!packs.empty() && packs.back() < items.front()) packs.pop_back();
if (packs.empty() || items.back() > packs.front()) return -1;
unsigned const items_total = accumulate(items.begin(), items.end(), 0U);
unsigned const packs_total = accumulate(packs.begin(), packs.end(), 0U);
if (items_total > packs_total) return -1;
unsigned const n = items.size();
unsigned const m = packs.size();
unsigned const N = 1 << n;
vector<unsigned> dist(N, make(m, 0));
dist[0] = make(0, 0);
for (unsigned S = 0; S < N; ++S) {
unsigned Z = (~S) & (N-1);
while (Z > 0) {
unsigned T = Z & ~(Z-1);
Z ^= T;
unsigned i = __builtin_ctz(T);
unsigned const x = items[i];
unsigned q = get_first(dist[S]);
unsigned w = get_second(dist[S]);
if (q >= m) continue;
w += x;
if (w > packs[q]) {
++q;
w = x;
if (q >= m || w > packs[q]) continue;
}
unsigned U = S | T;
auto p = make(q, w);
if (dist[U] > p) dist[U] = p;
}
}
auto res = get_first(dist.back());
if (res < m) return res + 1;
return -1;
}
}
int main()
{
iostream::sync_with_stdio(false);
cin.tie(NULL);
unsigned n, m;
cin >> n >> m;
vector<unsigned> items(n);
for (unsigned i = 0; i < n; ++i) {
cin >> items[i];
}
vector<unsigned> packs(m);
for (unsigned i = 0; i < m; ++i) {
cin >> packs[i];
}
int res = solve(move(items), move(packs));
if (res < 0) cout << "NIE\n";
else cout << res << '\n';
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #include <algorithm> #include <cassert> #include <iostream> using namespace std; namespace { unsigned make(unsigned a, unsigned b) { return (a << 27) | b; } unsigned get_first(unsigned p) { return p >> 27; } unsigned get_second(unsigned p) { return p & ((1U << 27) - 1); } int solve(vector<unsigned> items, vector<unsigned> packs) { sort(items.begin(), items.end()); sort(packs.begin(), packs.end(), greater<unsigned>()); if (packs.size() > items.size()) { packs.resize(items.size()); } while (!packs.empty() && packs.back() < items.front()) packs.pop_back(); if (packs.empty() || items.back() > packs.front()) return -1; unsigned const items_total = accumulate(items.begin(), items.end(), 0U); unsigned const packs_total = accumulate(packs.begin(), packs.end(), 0U); if (items_total > packs_total) return -1; unsigned const n = items.size(); unsigned const m = packs.size(); unsigned const N = 1 << n; vector<unsigned> dist(N, make(m, 0)); dist[0] = make(0, 0); for (unsigned S = 0; S < N; ++S) { unsigned Z = (~S) & (N-1); while (Z > 0) { unsigned T = Z & ~(Z-1); Z ^= T; unsigned i = __builtin_ctz(T); unsigned const x = items[i]; unsigned q = get_first(dist[S]); unsigned w = get_second(dist[S]); if (q >= m) continue; w += x; if (w > packs[q]) { ++q; w = x; if (q >= m || w > packs[q]) continue; } unsigned U = S | T; auto p = make(q, w); if (dist[U] > p) dist[U] = p; } } auto res = get_first(dist.back()); if (res < m) return res + 1; return -1; } } int main() { iostream::sync_with_stdio(false); cin.tie(NULL); unsigned n, m; cin >> n >> m; vector<unsigned> items(n); for (unsigned i = 0; i < n; ++i) { cin >> items[i]; } vector<unsigned> packs(m); for (unsigned i = 0; i < m; ++i) { cin >> packs[i]; } int res = solve(move(items), move(packs)); if (res < 0) cout << "NIE\n"; else cout << res << '\n'; return 0; } |
polski