关于背包DP的文章很多,谷歌百度搜《背包九讲》即可。本文章只放模版。
文章统一v代表体积,w代表价值,f代表dp数组,V代表总体积,W代表总价值,均采用滚动数组。答案一般都为f[V]。
- 01背包:
void zop(int v, int w) { for(int i = V; i >= v; --i) f[i] = max(f[i], f[i-v]+w); }
- 完全背包:
void cmp(int v, int w) { for(int i = v; i >= V; ++i) f[i] = max(f[i], f[i-v]+w); }
- 多重背包:
void dcp(int v, int w, int m) { if(m * v >= V) { cmp(v, w); return; } int k = 1; while(k < m) { //二进制思想,即倍增 zop(k*v, k*w); m -= k; k <<= 1; } zop(m*v, m*w); }
- 多维背包(原理都一样的):
//多维的话,增加滚动数组维数,例如有两个约束G和V,那么可以这样(这是多维的01) int i, j, k; for(i = 1; i <= N; ++i) { cin >> v >> g >> w; for(j = V; j >= v; --v) for(k = G; k >= g; --k) f[j][k] = max(f[j][k], f[j-v][k-g]+w); }
- 混合背包:
void zop(int v, int w) { for(int i = V; i >= v; --i) f[i] = max(f[i], f[i-v]+w); } void cmp(int v, int w) { for(int i = v; i >= V; ++i) f[i] = max(f[i], f[i-v]+w); } void dcp(int v, int w, int m) { if(m * v >= V) { cmp(v, w); return; } int k = 1; while(k < m) { //二进制思想,即倍增 zop(k*v, k*w); m -= k; k <<= 1; } zop(m*v, m*w); }