有各种类型的物品(N种类型),每种都有重量wi和成本ci。每个都有无穷无尽的数量。问题是制作具有EXACT(W)重量和最小物品总成本的背包。我知道在这种情况下我应该使用动态,但这不是通常的背包问题,我找不到关系。我也发现了一些类似的问题,但我还没有理解这些问题。以下是1,2的链接。 如何使用DP来解决它?
答案 0 :(得分:4)
f[0]=0;g[0]=true;
for (int i=0;i<N;i++)
for (int j=0;j<W;j++)
if (g[j]) {
g[j+w[i]]=true;
if (f[j+w[i]]==0||f[j+w[i]]>f[j]+c[i])
f[j+w[i]]=f[j]+c[i];
}
if (g[W]) return f[W];
else return 0;//impossible
答案 1 :(得分:2)
假设您想要找到最低费用,可以用来完成W
以及c_i > 0
和w_i > 0
的权重,然后我们可以将min_cost(i, W)
定义为最低仅使用权重为i
的{{1}}到N
的项目可以实现的费用
基本案例发生在我们只有一个项目时,因此W
时。在这种情况下,解决方案是:
i=N
因为如果我们不使用项目min_cost(N, 0) = 0
,那么我们的权重已经等于0
N
如果min_cost(N, W) = c_i * W / w_i
是W
的倍数,即w_i
W mod w_i = 0
否则,因为我们无法仅使用最后一项获得min_cost(N, W) = Infinity
的权重。
现在可以将经常性关系表述为:
直到W
min_cost(i, W) = min(c_i * k + min_cost(i+1, W - k * w_i))
k=0
经常性关系表明,我们将尽可能多地使用项目W - k*w_i < 0
,而我们的权重未超过i
。
然后,您可以使用memoization的递归算法实现此方法,并根据需要存储实际解决方案(重复中的W
)。
修改根据建议,如果我们发现有两种情况会影响k
,则可以实现加速。这种情况首先是不需要首先使用第i个项目min_cost(i, W)
,当我们要使用第i个项目至少一次时,这与min_cost(i+1, W)
相同,因为我们可能会使用项目min_cost(i, W - w_i)
不止一次。这会将我们的重现更改为以下内容:
i