ICPC2016 模擬国内予選B E ぼくのかんがえたさいきょうのおふとん
解法
使われているお布団の組み合わせが bitmask とする。この組み合わせでできる最小のコストを dp[bitmask] とする。ここに新しくお布団 i を下に差し込んでコストを下げられるかどうかを調べ、dp[bitmask & (1<
#include <bits/stdc++.h> using namespace std; int N, M; int64_t solve(const vector<int> &s, const vector<int> &d) { // dp[bitmask] := bitmask の組み合わせで出来る最小のコスト vector<int64_t> dp((1 << N), 1e9); queue<int> que; que.push(0); dp[0] = accumulate(d.begin(), d.end(), 0); while (!que.empty()) { int bitmask = que.front();// 使われているお布団の組み合わせ que.pop(); int64_t sum = 0; for (int i = 0; i < N; ++i) if (bitmask & (1 << i)) sum += s[i]; for (int i = 0; i < N; ++i) { if (bitmask & (1 << i)) continue;//既にお布団iが含まれているならスルー // お布団iを新たに追加する場合を考える int64_t cost = dp[bitmask]; for (int m = 0; m < M; ++m) { if (d[m] <= sum) continue;//お布団iを使わないほうが良い場合はスルー if (d[m] - sum > abs(d[m] - (sum + s[i]))) { cost -= (d[m] - sum); cost += abs(d[m] - (sum + s[i])); } } // 最小コストを更新する if (dp[bitmask | (1 << i)] <= cost) continue; dp[bitmask | (1 << i)] = cost; que.push(bitmask | (1 << i)); } } return *min_element(dp.begin(), dp.end()); } int main() { cin.tie(0); ios::sync_with_stdio(false); while (true) { cin >> N >> M; if (N == 0) break; vector<int> s(N); vector<int> d(M); for (int i = 0; i < N; ++i) cin >> s[i]; for (int i = 0; i < M; ++i) cin >> d[i]; cout << solve(s, d) << endl; } }