# 背包问题(二维求法) ## 求方案数 - 体积至多$j$ - 初始:$f[0][i]=1$,$0<=i<=m$,其余为$0$ - $01$背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] += f[i - 1][j - v]; } ``` - 完全背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] += f[i][j - v]; } ``` - 体积恰好$j$ - 初始:$f[i][0]=1$,$0<=i<=n$,其余为$0$ - $01$背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] += f[i - 1][j - v]; } ``` - 完全背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] += f[i][j - v]; } ``` - 体积至少$j$ - 初始:$f[0][0]=1$,其余为$0$ - $01$背包 - ```c++ for (int j = 0; j <= m; j++) f[i][j] = f[i - 1][j] + f[i - 1][max(0, j - v)]; ``` - 完全背包代码 - 有无穷多组方案数,不这么问 ## 求最大/小值 - 体积至多$j$ - 初始:$f[i,j]=0,0 <= i <= n, 0 <= j <= m$ - $01$背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = max(f[i][j], f[i - 1][j - v] + w); } ``` - 完全背包 - ```c++ for (int j = 1; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = max(f[i][j], f[i][j - v] + w); } ``` - 体积恰好$j$ - 求最小值 - 初始化$f[0][0]=0$,其它是$INF$ - 01 背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = min(f[i][j], f[i - 1][j - v] + w); } ``` - 完全背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = min(f[i][j], f[i][j - v] + w); } ``` - 求最大值 - 初始化$f[0][0]=0$, 其余是$−INF$ - 01背包  - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = max(f[i][j], f[i - 1][j - v] + w); } ``` - 完全背包 - ```c++ for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v) f[i][j] = max(f[i][j], f[i][j - v] + w); } ``` - 体积至少$j$ - 求最小值 - 初始化$f[0][0]=0$, 其余是$INF$ - 01背包  - ```c++ for (int j = 0; j <= m; j++) f[i][j] = min(f[i - 1][j], f[i - 1][max(0, j - v)] + w); ``` - 完全背包 - ```c++ for (int j = 0; j <= m; j++) f[i][j] = min(f[i - 1][j], f[i][max(0, j - v)] + w); ``` - 求最大值 - 没有求最大值的