正如@dasblinkenlight 评论的那样,这是整数背包问题(或者它的轻微变化,其中每个重量项目的数量w
可以达到C / w
)。
它有一个解O(n W)
,其中n
是不同项目的数量,W
是容器的容量。这个观察是由于 Sienna,算法设计手册(第 13.10 节背包问题,p428 标题下的所有大小都是相对较小的整数),我基于他对动态规划解决方案的建议来构建下面的算法和代码。
编辑:我刚刚阅读了@progenhard 的评论——是的,这也被称为Change Making Problem。
你要做的是从一个空容器开始,它可以完美地装满任何物品。然后您将每个项目添加到空容器中,以获得n
新的装满容器,即n
每个容器都只包含一个项目。然后将物品添加到新容器中,然后冲洗并重复,直到超过最大容量W
。有n
最大W
容量的选择,因此O(n W)
.
向后查看容器以找到已完全填充的最大容器是一件简单的事情,但在下面的 C++ 代码中,我只是打印出整个容器数组。
#include <iostream>
#include <vector>
using std::vector;
int main(int argc, char* argv[])
{
const int W = 25;
const int ws[] = { 5, 10, 20 };
const int n = sizeof(ws) / sizeof(int);
typedef std::vector<int> wgtvec_t;
typedef std::vector<wgtvec_t> W2wgtvec_t;
// Store a weight vector for each container size
W2wgtvec_t W2wgtvec(W +1);
// Go through all capacities starting from 0
for(int currCapacity=0; currCapacity<W; ++currCapacity) {
const wgtvec_t& currWgtvec = W2wgtvec[currCapacity];
// If we have a solution for capacity currCapacity, find other solutions
if (currCapacity==0 || !currWgtvec.empty()) {
for(int i=0; i<n; ++i) {
const int increaseCapacity = ws[i];
const int newCapacity = currCapacity + increaseCapacity;
if (newCapacity <= W) {
wgtvec_t& newWgtvec = W2wgtvec[newCapacity];
// Update new capacity if it doesn't already have a solution
if (newWgtvec.empty()) {
newWgtvec = currWgtvec;
newWgtvec.push_back(increaseCapacity);
}
}
}
}
}
// Print out all our solutions
for(int currCapacity=1; currCapacity<=W; ++currCapacity) {
using std::cout;
const wgtvec_t& currWgtvec = W2wgtvec[currCapacity];
if (!currWgtvec.empty()) {
cout << currCapacity << " => [ ";
for(wgtvec_t::const_iterator i=currWgtvec.begin(); i!=currWgtvec.end(); ++i) {
cout << *i << " ";
}
cout << "]\n";
}
}
return 0;
}
这种情况的输出是
5 => [ 5 ]
10 => [ 10 ]
15 => [ 5 10 ]
20 => [ 20 ]
25 => [ 5 20 ]
有一个更有趣的问题
const int W = 26;
const int ws[] = { 3, 5, 10, 20 };
输出是
3 => [ 3 ]
5 => [ 5 ]
6 => [ 3 3 ]
8 => [ 3 5 ]
9 => [ 3 3 3 ]
10 => [ 10 ]
11 => [ 3 3 5 ]
12 => [ 3 3 3 3 ]
13 => [ 3 10 ]
14 => [ 3 3 3 5 ]
15 => [ 5 10 ]
16 => [ 3 3 10 ]
17 => [ 3 3 3 3 5 ]
18 => [ 3 5 10 ]
19 => [ 3 3 3 10 ]
20 => [ 20 ]
21 => [ 3 3 5 10 ]
22 => [ 3 3 3 3 10 ]
23 => [ 3 20 ]
24 => [ 3 3 3 5 10 ]
25 => [ 5 20 ]
26 => [ 3 3 20 ]