关于背包问题的题目,前人之述备矣,这里只讨论实现
输入:
n
ca
w_1 v_1
w_2 v_2
...
w_n v_n
其中,n是物品总数,ca是背包大小,w_n是第n个物品的重量,v_n是第n个物品的价值
输出:
v_1 x
v_2 x
v_3 x
...
其中,v_n是当前情况为x时背包的价值,x是一串序列,由0,1组成,表示是否放入背包
如: 1001就表示第一个和最后一个物品放入背包,中间两个物品不放入
要求编写一个程序,输出所有可满足解.
思路很简单,就是穷举.穷举每一个情况.
伪代码如下:
f() { if (没有可以放进背包的东西) { 输出 } else { 放进背包 f() 不放进背包 f() 恢复原状 } }
这样,就构造了一个二叉树,可以输出每一种可选解的情况.
我的代码如下:
1 #include <iostream> 2 #include <functional> 3 4 struct Pack { 5 unsigned cnt; 6 unsigned *w; // weights 7 unsigned *v; // values 8 unsigned *x; // put in or not 9 unsigned ca; // capacity 10 11 Pack(unsigned items_cnt) : cnt(items_cnt) { 12 w = new unsigned [items_cnt]; 13 v = new unsigned [items_cnt]; 14 x = new unsigned [items_cnt]; 15 16 for (int i = 0; i < items_cnt; ++i) { 17 w[i] = v[i] = x[i] = -1; 18 } 19 } 20 21 ~Pack() { 22 delete [] w; 23 delete [] v; 24 delete [] x; 25 } 26 }; 27 28 29 int main() { 30 unsigned c; 31 32 std::cin >> c; 33 34 Pack p(c); 35 36 std::cin >> p.ca; 37 38 for (int i = 0; i < p.cnt; ++i) { 39 std::cin >> p.w[i] >> p.v[i]; 40 } 41 42 43 44 45 std::function<unsigned()> totval = [&]() { 46 unsigned cnt = 0; 47 48 for (int i = 0; i < p.ca; ++i) { 49 if (p.x[i] == 1) cnt += p.v[i]; 50 } 51 52 return cnt; 53 }; 54 55 std::function<unsigned()> totwt = [&]() { 56 unsigned cnt = 0; 57 58 for (int i = 0; i < p.ca; ++i) { 59 if (p.x[i] == 1) cnt += p.w[i]; 60 } 61 62 return cnt; 63 }; 64 65 std::function<void()> loop = [&]() { 66 unsigned no = -1; 67 for (int i = 0; i < p.cnt; ++i) { 68 if (p.x[i] == -1) { 69 no = i; 70 break; 71 } 72 } 73 74 if (no == -1) { 75 std::cout << totval() << ' '; 76 for (int i = 0; i < p.cnt; ++i) { 77 std::cout << p.x[i]; 78 } 79 std::cout << std::endl; 80 } else { 81 p.x[no] = 0; 82 loop(); 83 84 p.x[no] = 1; 85 86 if (totwt() <= p.ca) { 87 loop(); 88 } 89 90 p.x[no] = -1; 91 } 92 }; 93 94 loop(); 95 96 return 0; 97 }
测试数据:
5 15 9 8 1 2 3 8 1 0 3 9
输出:
0 00000 9 00001 0 00010 9 00011 8 00100 17 00101 8 00110 17 00111 2 01000 11 01001 2 01010 11 01011 10 01100 19 01101 10 01110 19 01111 8 10000 17 10001 8 10010 17 10011 16 10100 25 10101 16 10110 10 11000 19 11001 10 11010 19 11011 18 11100 18 11110
可以找到最优解,10101.