本代码中的几个函数可以作为“0-1背包”、“完全背包” 和“多重背包”的模板:
#include <iostream> #define INF 100000000 using namespace std; int f[240005]; //f[j]相当于f[i][j]: 考虑1...i个物品,恰好放到容量为j,所能达到的最大价值 int v; //背包容量 //处理一个完全背包 (该种物品不限量) void complete_pack(int *a, int c, int w) { for(int i = c; i <= v; i++) a[i] = max(a[i], a[i - c] + w); } //处理一个 01背包 (该种物品只有一个) void zeroone_pack(int *a, int c, int w) { for(int i = v; i >= c; i--) a[i] = max(a[i], a[i - c] + w); } //处理一个多重背包 (该种物品指定上限) void mutiple_pack(int *a, int c, int w, int m) { //该种物品足以塞满背包-->转化为完全背包 if(c * m >= v){ complete_pack(a, c, w); return; } /*二进制思想拆分:多重背包中的一个物品--变成-->0-1背包中的多个物品 容量:2^0 2^1 2^2 2^k m-∑前面 ***保证k达到最大值 价值:2^0*c 2^1*c 2^2*c 2^k*c (m-∑前面 )*c */ int k = 1; while(k < m) { zeroone_pack(a, k * c, k * w); m = m - k; k = 2 * k; } zeroone_pack(a, c * m, w * m); } int main() { //freopen("d:/data.in","r",stdin); //freopen("d:/data.out","w",stdout); int sum, i, c[7], w[7], m[7],cas = 0; while(scanf("%d%d%d%d%d%d", &m[1], &m[2], &m[3], &m[4], &m[5], &m[6])){ if(m[1] == 0 && m[2] == 0 && m[3] == 0 && m[4] == 0 && m[5] == 0 && m[6] == 0) break; sum = 0; for(i = 1; i <= 6; i++){ c[i] = w[i] = i; sum += c[i] * m[i]; } printf("Collection #%d:\n", ++cas); if(sum & 1){ puts("Can't be divided.\n"); }else{ sum /= 2; v = sum; for(i = 1; i <= sum; i++) f[i] = -INF; f[0] = 0; for(i = 1; i <= 6; i++) mutiple_pack(f, c[i], w[i], m[i]); if(f[v] < 0){ puts("Can't be divided.\n"); }else{ puts("Can be divided.\n"); } } } system("pause"); return 0; }