我可以在这里给出一个 O(n^3) 算法。不知道这个问题是否可以进一步优化到O(n^2)。
首先,这个问题是最大化if items的数量,这与其他背包问题有点不同。同时,它也有一个限制,即只有当背包的总价值大于其自身价值时,才能选择单个物品。所以一个明显的推论是,在选择相同数量的物品和固定总大小的情况下,总价值应该尽可能大(以便可以将更多物品添加到背包中)。
注意物品的数量n(<=100)和背包的大小K(<=1000)不是很大,设f[i][j]表示选择i个总大小为j的物品时的最大值。最初,所有 f[i][j] 都设置为 0,除了 f[0][0]=V。
然后根据需要添加的最小值对项目进行排序。这是一个贪心的想法,因为在排序之后,我们只能遍历每个项目一次。
DP 方法如下所示:
for (int k=0;k<n;k++) //iterate items
for (int i=n;i>=0;i--)
for (int j=K;j>=0;j--) if (item.M[k]<=f[i][j])
f[i+1][j+item.S[k]]=max(f[i+1][j+item.S[k]],f[i][j]+item.V[k]);
最终答案(最大项目数)是:
for (int i=n;i>=0;i--)
for (int j=0;j<=K;j++)
if (f[i][j]) return i;