演算法競賽高階指南, 281 頁, 多重揹包(此處**抄書上的)
題目意思:
n種硬幣,每種硬幣的幣值 a[i], 數量c[i], 給出乙個數值m 求出可以拼成 1 ~ m 這 m種幣值的哪幾種?
本題要點:
1、 多重揹包 的 「直接拆分法」,
bool f[maxm]; //在階段i, f[j] 表示前i種硬幣是否能拼成面值j
在狀態i(遍歷到第i中硬幣時候)
for(int k = m; k >= a[i]; --k) //幣值 f[k] = f[k] | f[k - a[i]];
2、 貪心策略
int used[maxm]; //在階段i, used[j] 表示 f[j]在階段i 為true ,至少需要多少枚第i種硬幣
在 i階段, 面值j能夠拼出來, 也就是f[j] == true的條件有2個:
1、 如果 f[j] 原來就是 true, 不進行狀態轉移,而且 used[j] == 0
2、 f[j] == false, 面值 j - a[i] 能夠拼出來(f[j - a[i]] == true),
而且當前已經使用的 i 種硬幣還有貨可以用(used[j - a[i]] < c[i])
if(!f[j] && f[j - a[i]] && used[j - a[i]] < c[i])
#include
#include
#include
using
namespace std;
const
int maxm =
100010
;const
int maxn =
110;
bool f[maxm]
;//在階段i, f[j] 表示前i種硬幣是否能拼成面值j
int used[maxm]
;//在階段i, used[j] 表示 f[j]在階段i 為true ,至少需要多少枚第i種硬幣
int a[maxn]
;int c[maxn]
;int n, m;
void
solve()
for(
int j = a[i]
; j <= m;
++j)}}
int ans =0;
for(
int i =
1; i <= m;
++i)
printf
("%d\n"
, ans);}
intmain()
for(
int i =
1; i <= n;
++i)
solve()
;}return0;
}/*3 10
1 2 4 2 1 1
2 51 4 2 1
0 0*//*8
4*/
poj 1742 Coins 多重揹包
題意很簡單,有n種硬幣,每種硬幣面額多大,有多少個,求可以構成m以內的面額有多少種。開始用的是普通的多重揹包的求法,裸裸的超時了,看了別人的 發現可以優化很多。用usea這個來儲存用來多少個a硬幣,避免的很多無用的計算。先貼以前超時的 include include int dp 100005 in...
POJ 1742 Coins 多重揹包DP
題意 有n種面額的硬幣。面額 個數分別為a i c i,求最多能搭配出幾種不超過m的金額?思路 dp j 就是總數為j的價值是否已經有了這種方法,如果現在沒有,那麼我們就乙個個硬幣去嘗試直到有,這種價值方法有了的話,那麼就是總方法數加1。多重揹包可行性問題 傳統多重揹包三重迴圈會超時,因為只考慮是否...
poj1742 Coins 多重揹包優化DP
給定n個物品,第i個物品價值為a i 數量為c i 求可以組成的小於m的價值的個數。好像n,m的範圍比較大,暴力跑二進位制優化的多重揹包是可以卡過去的。但是有一種o nm o n m 的方法來優化多重揹包,即在列舉體積的時候我們按照完全揹包來順序列舉,完全揹包裡的列舉體積是可以滿足重複選擇同意物品的...