硬幣思考多重揹包

2022-02-15 23:58:38 字數 2549 閱讀 4592

給定n種硬幣,其中第 i 種硬幣的面值為ai,共有ci個。

從中選出若干個硬幣,把面值相加,若結果為s,則稱「面值s能被拼成」。

求1~m之間能被拼成的面值有多少個。

輸入包含多組測試用例。

每組測試用例第一行包含兩個整數n和m。

第二行包含2n個整數,分別表示a1,a2,…,an和c1,c2,…,cn。

當輸入用例n=0,m=0時,表示輸入終止,且該用例無需處理。

每組用例輸出乙個結果,每個結果佔一行。

1≤n≤100,

1≤m≤105,

1≤ai≤105,

1≤ci≤1000

3 10

1 2 4 2 1 1

2 51 4 2 1

0 0

8

4

先不看題

對於多重揹包, 可以拆成01揹包來做

unsigned int f[maxn];

memset(f, 0, sizeof f);

f[0] = 0;

for (int i = 1; i <= n; ++i)

for (int j = 1; j <= c[i]; ++j)

for (int k = m; k >= v[i]; --k)

f[k] = max(f[k], f[k - v[i]] + w[i]);

int ans = 0;

for (int i = 0; i <= m; ++i)

ans = max(maxn, f[i]);

\(c_i\)拆成p + 2個物品

\(2^0\) * \(v_i\), \(2^1\) * \(v_i\), ... , \(2^p\) * \(v_i\), \(r_i\) * \(v_i\)

雖然沒佇列優化快,但是好寫

unsigned int f[maxn];

int nw[maxn * log2(maxn)], nv[maxn * log2(maxn)];

int cnt = 0;

for (int i = 1; i <= n; ++i)

if (s[i]) nw[++cnt] = s[i] * w[i], nv[cnt] = s[i] * v[i];

}memset(f, 0, sizeof f);

for (int i = 1; i <= cnt; ++i)

for (int j = m; j >= nv[i]; --j)

f[j] = max(f[j], f[j - nv[i]] + nw[i]);

#include using namespace std;

const int maxn = 2005;

int n, v[maxn], w[maxn], c[maxn], q[maxn], m, f[maxn];

int calc(int u, int i, int k)

int main()

for (int p = maxp; p; --p)}}

}int ans = 0;

for (int i = 1; i <= m; ++ i) ans = max(ans, f[i]);

printf("%d", ans);

return 0;

}

好了來看題, 一定要注意到我們只關注可行性,而不關注最優解

暴力01揹包

bool f[maxn];

memset(f, 0, sizeof);

f[0] = 1;

for (int i = 1; i <= n; ++i)

for (int j = 1; j <= c[i]; ++j)

for (int k = m; k >= a[i]; --k)

f[k] |= f[k - a[i]];

必定超時, 但是這道題是可行性為題, 不需要最優解

我們發現,若前i種硬幣能湊出 sum/2, 只有兩種情況:

1.在i階段之前, 就已經f[j] = true

2.在i階段之前, 就已經f[j - i] = true

於是,可以貪心, 設used[j] 表示f[j]在階段i是為true的情況下至少需要多少塊i種硬幣

這樣上面的** for(j) for(k) 迴圈可以優化為1維,直接正序掃面

當(!f[j] && f[j - i] && used[j - i] < a[i])才可以轉移

巧妙利用其只求可行性,既不二分也不單調佇列

#include using namespace std;

const int maxn = 1e5 + 5;

int a[101], c[101], n, m;

int f[maxn], cnt, used[maxn];

int main()

cout << cnt << '\n';

} return 0;

}

多重揹包問題 硬幣

給定n種硬幣,其中第 i 種硬幣的面值為ai,共有ci個。從中選出若干個硬幣,把面值相加,若結果為s,則稱 面值s能被拼成 求1 m之間能被拼成的面值有多少個。輸入格式 輸入包含多組測試用例。每組測試用例第一行包含兩個整數n和m。第二行包含2n個整數,分別表示a1,a2,an和c1,c2,cn。當輸...

最少硬幣問題(多重揹包)

time limit 1000 ms memory limit 65536 kib submit statistic problem description 設有n種不同面值的硬幣,各硬幣的面值存於陣列t 1 n 中。現要用這些面值的硬幣來找錢。可以使用的各種面值的硬幣個數存於陣列coins 1 n...

python多重揹包 多重揹包

多重揹包問題 有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。資料範圍 0 n v 100 0 vi wi si 100 樸素版多重揹包問題 樸素版完全揹包問...