★、背包求方案数的时候,多重背包是不行的,因为产生重复的背包会有多种情况。
★、背包记录路径的时候,其实是不行的,因为更新了12的最优解,如果它依赖于6这个背包,然后你后面改变了6这个背包,就GG
1、01背包问题。
tot:总背包空间,vall[i]:每件物品的价值,w[i]:每件物品的重量
http://acm.hdu.edu.cn/showproblem.php?pid=2602
01背包明显可以只写一维的,所以二维的就不写了。
关于为什么可以只写一维的呢?这就和你枚举的顺序有关了。从tot 枚举 到 w[i]。那么是优先更新dp[比较大的数]
而且是从dp[i - 1][]那里更新过来的。至于后面枚举小的背包容量的时候,较大的背包容量是用不了的了,所以这里就可以避免有重复使用的bug。确保都是从dp[i- 1]枚举过来。而这个顺序反转了的话,刚好的完全背包的最优解。这个后面再说
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 1e3 + 20; int dp[maxn]; int w[maxn], val[maxn]; void work() { memset(dp, 0, sizeof dp); int n, tot; scanf("%d%d", &n, &tot); for (int i = 1; i <= n; ++i) { scanf("%d", &val[i]); } for (int i = 1; i <= n; ++i) { scanf("%d", &w[i]); } for (int i = 1; i <= n; ++i) { for (int j = tot; j >= w[i]; --j) { dp[j] = max(dp[j], dp[j -w[i]] + val[i]); } } printf("%d\n", dp[tot]); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif int t; scanf("%d", &t); while (t--) work(); return 0; }