[C++11][算法][穷举]输出背包问题的所有可满足解

关于背包问题的题目,前人之述备矣,这里只讨论实现

 

输入:

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 
 2 #include 
 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 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 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.

 

转载于:https://www.cnblogs.com/jt2001/p/packquestionall.html

你可能感兴趣的:([C++11][算法][穷举]输出背包问题的所有可满足解)