POJ 1742 Coins 多重揹包,高階指南

2021-10-06 07:23:31 字數 1494 閱讀 1250

演算法競賽高階指南, 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 的方法來優化多重揹包,即在列舉體積的時候我們按照完全揹包來順序列舉,完全揹包裡的列舉體積是可以滿足重複選擇同意物品的...